awk 概述
AWK是一種優良的文本處理工具,Linux及Unix環境中現有的功能最強大的數據處理引擎之一。這種編程及數據操作語言的最大功能取決於一個人所擁有的知識。awk命名:Alfred Aho Peter 、Weinberger和brian kernighan三個人的姓的縮寫。
awk---->gawk 即: gun awk
在linux上常用的是gawk,awk是gawk的鏈接文件
man gawk---->pattern scanning and processing language模式掃描和處理語言。
pattern [pætn] 模式 ; process[prəʊses]處理
任何awk語句都是由模式和動作組成,一個awk腳本可以有多個語句。模式決定動作語句的觸發條件和觸發時間。
模式:
正則表達式 :/root/ 匹配含有root的行 /*.root/
關係表達式: < > && || + ***
匹配表達式: ~ !~
動作:
變量 命令 內置函數 流控制語句
它的語法結構如下:
awk [options] 'BEGIN{ print “start” }pattern{ commands }’END{ print “end” }'file
其中:BEGIN END是AWK的關鍵字部,因此必須大寫;這兩個部分開始塊和結束塊是可選的
awk 的鞏工作模式
和sed 命令類似,從上向下一次遍歷
語法格式:
- awk ‘BEGIN{}parttern{commands} END{}’ file——name
- stabdard output (標準輸出) |awk ‘BEGIN{} pattern{commands}END{}’
語法格式說明:
BEGIN{}:正式處理數據之前執行
pattern 匹配模式
{commands} 處理命令,可能多行
END{} 處理玩所有匹配數據後執行
awk 的內置變量
內置變量 | 含義 |
---|---|
$0 | 打印整行內容 |
n | 打印當前行的第1-n個字段 |
NF | 當前行的字段個數,也就是有多少列 |
NR | 當前行的行號,從1開始計數 |
FNR | 多文件處理時,每個文件行號單獨計數,都是從0 開始 |
FS | 輸入字段分割符,不指定默認以空格或tab鍵分割 |
RS | 輸入行分割符,默認回車換行 |
OFS | 輸入字段分割符,默認爲空格 |
ORS | 輸出行分割符,默認爲回車換行 |
FILENAME | 處理文件的文件名 |
ARGC | 命令行參數個數 |
ARGV | 命令行參數數組 |
- $0 打印整行內容
[root@localhost ~]# awk '{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
……
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
[root@localhost ~]#
[root@localhost ~]# awk 'BEGIN{FS=":"} {print $1}' /etc/passwd #以:分隔符,打印第一字段
root
bin
daemon
adm
……
sshd
postfix
[root@localhost ~]#
[root@localhost ~]# awk 'BEGIN{FS=":"} {print $2}' /etc/passwd
#打印/etc/passwd 文件的第二個字段
x
x
x
……
x
x
[root@localhost ~]#
# 打印每一行的第7個字段
[root@localhost ~]# awk 'BEGIN{FS=":"} {print $7}' /etc/passwd
/bin/bash
/sbin/nologin
/sbin/nologin
……
/sbin/nologin
/sbin/nologin
/sbin/nologin
/sbin/nologin
[root@localhost ~]#
## 默認是以空格鍵和tab鍵 爲分隔符。如果不需要特定指定分隔符,就不需要加'BEGIN{FS="分隔符"}'
[root@hbs ~]# cat list
Hadoop Spark Flume
Java Python Scala
Allen Mike Meggie
[root@hbs ~]#
[root@hbs ~]# awk '{print $1}' list
Hadoop
Java
Allen
[root@hbs ~]#
[root@hbs ~]# awk 'BEGIN{FS=":"} {print $NF}' /etc/passwd
/bin/bash
/sbin/nologin
/sbin/nologin
/sbin/nologin
……
# $NF 通常可以表示一行的最大值,最後一個數
- NF 當前行的字段個數,也就是有多少列
[root@hbs ~]# vim list
[root@hbs ~]# cat list
Hadoop Spark Flume #這行有3個字段
Java Python Scala GO #這行有4個字段 #tab鍵 沒有哦佔用啊
Allen Mike Meggie #這行有3個字段
[root@hbs ~]#
[root@hbs ~]# awk '{print NF}' list
3
4
3
[root@hbs ~]#
[root@hbs ~]# awk '{print NR}' list #輸出行號有哪些
1
2
3
[root@hbs ~]#
#當接多個文件後,發現他是累計計算的,so出現等多個文件就會單獨計數FNR
[root@hbs ~]# awk '{print NR}' list /etc/passwd
1
2
3
4
5
6
7
……
21
[root@hbs ~]#
[root@hbs ~]# awk '{print FNR}' list /etc/passwd list和/etc/passwd 單獨計數
1
2
3
1
2
3
4
……
17
18
[root@hbs ~]#
- FS 輸入字段分割符,不指定默認以空格或tab鍵分割
[root@hbs ~]# vim list
[root@hbs ~]# cat list
Hadoop|Spark:Flume
Java|Python:Scala:GO
Allen|Mike:Meggie
[root@hbs ~]# awk '{print $2}' list #默認以空格爲分隔符,所以沒顯示
[root@hbs ~]#
#以|符分隔 ‘BEGIN{FS="分割符"} {print $n}’ file
[root@hbs ~]# awk 'BEGIN{FS="|"} {print $1}' list
Hadoop
Java
Allen
[root@hbs ~]#
#以 : 分割 字段
[root@hbs ~]# awk 'BEGIN{FS=":"} {print $2}' list
Flume
Scala
Meggie
[root@hbs ~]#
- RS 輸入行分割符,默認回車換行 默認是回車,如果不是回車,自定義的話需要RS 指定
[root@hbs ~]# cat tianzhen
Hadoop|Spark|Flume---java|Python|Scala|Go---Allen|Mike|Meggie
[root@hbs ~]#
[root@hbs ~]# awk 'BEGIN{RS="---"} {print $0}' tianzhen
Hadoop|Spark|Flume
java|Python|Scala|Go
Allen|Mike|Meggie
[root@hbs ~]#
#先以行顯示,在以|分割
[root@hbs ~]# awk 'BEGIN{RS="---";FS="|"} {print $3}' tianzhen
Flume
Scala
Meggie
[root@hbs ~]#
- ORS 輸出行分割符,默認爲回車換行
[root@hbs ~]# awk 'BEGIN{RS="---";FS="|";ORS="****"} {print $3}' tianzhen
Flume****Scala****Meggie
****[root@hbs ~]#
- OFS
[root@hbs ~]# awk 'BEGIN{RS="***"};FS="---";OFS=":" {print $1,$3}' tianzhen
Hadoop|Spark|Flume---java|Python|Scala|Go---Allen|Mike|Meggie
Hadoop|Spark|Flume---java|Python|Scala|Go---Allen|Mike|Meggie:
[root@hbs ~]#
# 一般寫腳本時候,不會常用這三個
- FILENAME 處理文件的文件名
[root@hbs ~]# awk '{print FILENAME}' tianzhen (文件名)
tianzhen
tianzhen
tianzhen
[root@hbs ~]#
[root@hbs ~]# awk '{print FILENAME}' list (文件名)
list
list
list
[root@hbs ~]#
awk 格式化輸出值printf
格式化 | 含義 |
---|---|
%s | 打印字符串 |
%d | 打印十進制數字 |
%f | 打印一個浮點數 |
%x | 打印十六進制數 |
%o | 打印八進制數字 |
%e | 打印數字科學技術法形式 |
%c | 打印單個字符的ASCII碼 |
printf 默認是沒有換行格式的
[root@hbs ~]# awk 'BEGIN{FS=":"} {printf $1}' /etc/passwd
rootbindaemonadmlpsyncshutdownhaltmailoperatorgamesftpnobodysystemd-networkdbuspolkitdsshdpostfix[root@hbs ~]#
[root@hbs ~]# awk 'BEGIN{FS=":"} {printf "%s\n",$1}' /etc/passwd
root
bin
daemon
……
sshd
postfix
[root@hbs ~]#
#打印第一個和第7個字段
[root@hbs ~]# awk 'BEGIN{FS=":"} {printf "%s %s\n",$1,$7}' /etc/passwd
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
……
sshd /sbin/nologin
postfix /sbin/nologin
[root@hbs ~]#
#打印第一個和第7個字段 ,但是每個字段都需要站位20個字符串
[root@hbs ~]# awk 'BEGIN{FS=":"} {printf "%20s %20s\n",$1,$7}' /etc/passwd
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
……
dbus /sbin/nologin
polkitd /sbin/nologin
sshd /sbin/nologin
postfix /sbin/nologin
[root@hbs ~]#
# 這裏發現右邊對的是齊的,用+ - 號對齊,默認是左對齊
# 左對齊的方式打印
[root@hbs ~]# awk 'BEGIN{FS=":"} {printf "%-20s %-20s\n",$1,$7}' /etc/passwd
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
……
sshd /sbin/nologin
postfix /sbin/nologin
[root@hbs ~]#
格式舉例:
1、以字符串格式打印 /etc/passwd 的第7 個字段,一冒號 最爲分隔符
[root@hbs ~]# awk 'BEGIN{FS=":"} {printf "%s",$7}' /etc/passwd
/bin/bash/sbin/nologin/sbin/nologin/sbin/nologin/sbin/nologin/bin/sync/sbin/shutdown/sbin/halt/sbin/nologin/sbin/nologin/sbin/nologin/sbin/nologin/sbin/nologin/sbin/nologin/sbin/nologin/sbin/nologin/sbin/nologin/sbin/nologin[root@hbs ~]#
# 加上回車換行
[root@hbs ~]# awk 'BEGIN{FS=":"} {printf "%s\n",$7}' /etc/passwd
/bin/bash
/sbin/nologin
……
/sbin/nologin
/sbin/nologin
[root@hbs ~]#
# 多個換行
[root@hbs ~]# awk 'BEGIN{FS=":"} {printf "%s\n\n\n",$7}' /etc/passwd
/bin/bash
/sbin/nologin
/sbin/nologin
……
/sbin/nologin
[root@hbs ~]#
2、以十進制格式打印 /etc/passwd 第三個字段,一冒號作爲分隔符
[root@hbs ~]# awk 'BEGIN{FS=":"} {printf "%d\n",$3}' /etc/passwd
0
1
2
3
……
81
999
74
89
[root@hbs ~]#
常用就這2個,其它瞭解即可
awk 匹配的兩種用法
- 迴歸工作模式:
讀取文本中的一行行數據,首先依據我們的pattern(匹配模式)匹配,如果匹配有就處理,沒有就不處理,繼續第二行匹配,有就處理,沒有就不匹配,繼續下一行,一直到匹配完所有文本
1 、 正則表達式
2、關係運算的匹配
正則匹配
匹配/etc/passwd 文件中含有root字符串的所有信息
[root@hbs ~]# awk 'BEGIN{FS=":"}/root/{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@hbs ~]#
匹配/etc/passwd 文件中含有ftp 開頭的所有行
[root@hbs ~]# awk 'BEGIN{FS=":"}/^ftp/{print $0}' /etc/passwd
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
[root@hbs ~]#
關係運算符匹配
運算符 | 含義 |
---|---|
< | 小於 |
> | 大於 |
<= | 小於等於 |
>= | 大於等於 |
== | 等於 |
!= | 不等於 |
~ | 匹配正則表達式 |
!~ | 不匹配正則表達式 |
以冒號爲分割符,匹配/etc/passwd 文件中第三個字小安與50的所有信息
[root@hbs ~]# awk 'BEGIN{FS=":"}$3<50{print $3}' /etc/passwd
0
1
2
……
11
12
14
[root@hbs ~]#
以冒號爲分割符,匹配/etc/passwd 文件中第三個字段大與50的所有信息
[root@hbs ~]# awk 'BEGIN{FS=":"}$3>50{print $3}' /etc/passwd
99
192
81
999
74
89
[root@hbs ~]#
以冒號爲分割符,匹配/etc/passwd 文件中第7個字段爲/bin/bash 的所有信息
[root@hbs ~]# awk 'BEGIN{FS=":"}$7=="/bin/bash"{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
[root@hbs ~]#
以 冒號分割符 ,匹配/etc/passwd 中第三個 字符串 包含3個以上數字的所有行信息
[root@hbs ~]# awk 'BEGIN{FS=":"}$3~/[0-9](3,)/{print $3}' /etc/passwd
[root@hbs ~]#
布爾運算符
|| 或者
&& 與
! 非
以冒號爲分隔符 , 匹配/etc/passwd 文件中 包含ftp 或wyh 的所有行信息
[root@hbs ~]# awk 'BEGIN{FS=":"}$1=="ftp"||$1=="wyh"{print $0}' /etc/passwd
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
[root@hbs ~]#
以冒號分割符,匹配 /etc/passwd 文件中第三個字段小於50 並且第4個字段大於50的所有信息
[root@hbs ~]# awk 'BEGIN{FS=":"}$3<=50 && $4 >= 50 {print $0}' /etc/passwd
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
[root@hbs ~]#
awk 動作中的表達式用法
運算符 | 含義 |
---|---|
+ | 加 |
- | 減 |
* | 乘 |
/ | 除 |
^或者** | 乘方 |
++X | 在返回x變量前,x變量+1 (加在前,先+) |
X++ | 在返回後,x變量+1 |
[root@hbs ~]# awk 'BEGIN{var=20;var1="hello";print var,var1}'
20 hello
[root@hbs ~]#
# num1 沒有定義 ,默認爲0
[root@hbs ~]# awk 'BEGIN{num1=20;num2+=num1;print num1,num2}'
20 20
[root@hbs ~]#
# num 2 除以 num 1
[root@hbs ~]# awk 'BEGIN{num1=20;num2=100;print num2/num1}'
5
[root@hbs ~]#
[root@hbs ~]# awk 'BEGIN{num1=20;num2=30;printf "%f\n",num1/num2}'
0.666667
[root@hbs ~]#
awk 動作中的條件及循環語句
- 條件語句
if(條件表達式)
動作1
else if(條件表達式)
動作2
else
動作3
以冒號 分割符 ,值打印 /etc/passwd 中第3個字段的數值在50~100 範圍內的信息
[root@hbs ~]# awk 'BEGIN{FS=":"}{if($3>50 && $3<100) print $0}' /etc/passwd
nobody:x:99:99:Nobody:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
[root@hbs ~]#
等價於這樣:
[root@hbs ~]# awk 'BEGIN{FS=":"}$3 >=50 && $3 <=100{print $0}' /etc/passwd
nobody:x:99:99:Nobody:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
[root@hbs ~]#
[root@hbs ~]# awk 'BEGIN{FS=":"}{if($3<50) printf "%s%d","小於50的uid",$3}' /etc/passwd
小於50的uid0小於50的uid1小於50的uid2小於50的uid3小於50的uid4小於50的uid5小於50的uid6小於50的uid7小於50的uid8小於50的uid11小於50的uid12小於50的uid14[root@hbs ~]#
# 沒加 \n 換行的效果
[root@hbs ~]# awk 'BEGIN{FS=":"}{if($3<50) printf "%s%d\n","小於50的uid",$3}' /etc/passwd
小於50的uid0
小於50的uid1
小於50的uid2
小於50的uid3
小於50的uid4
小於50的uid5
小於50的uid6
小於50的uid7
小於50的uid8
小於50的uid11
小於50的uid12
小於50的uid14
[root@hbs ~]#
[root@hbs ~]# awk 'BEGIN{FS=":"}{if($3<50) printf "%-10s %-5d\n","小於50的uid",$3}' /etc/passwd
小於50的uid 0
小於50的uid 1
小於50的uid 2
小於50的uid 3
小於50的uid 4
小於50的uid 5
小於50的uid 6
小於50的uid 7
小於50的uid 8
小於50的uid 11
小於50的uid 12
小於50的uid 14
- 循環語句 do while
do while
do
動作
while (條件表達式)
- for循環
for
for (初始化計數器;計數器測試;計數器變更)
動作
計算1+2+3+4+5+……+100的和,請使用while、do while、for 三種循環方式實現
while 循環
[root@hbs ~]# cat while.sh
BEGIN {
while (i<=100)
{
sum+=i
i++
}
print sum
}
[root@hbs ~]# awk -f while.sh # -f引用
5050
[root@hbs ~]#
for 循環
[root@hbs ~]# cat for.sh
BEGIN{
for(i=0;i<=100;i++)
{
sum+=i
}
print sum
}
[root@hbs ~]# awk -f for.sh
5050
[root@hbs ~]#
do while
[root@hbs ~]# cat do_while.sh
BEGIN{
do
{
sum+=i
i++
}
while (i<=100)
print sum
}
[root@hbs ~]# awk -f do_while.sh
5050
[root@hbs ~]#
awk 選項總結
選項 | 含義 |
---|---|
-v | 參數傳遞 |
-f | 指定腳本文件 |
-F | 之地那個分割符 |
-V | 查看awk的版本號 |
-v 定義或引用變量
[root@hbs ~]# awk -v num2="$num1" -v var1="$var" 'BEGIN{print num2,var1}'
20 hello
[root@hbs ~]#
-f 指定awk 命令文件
[root@hbs ~]# cat do_while.sh
BEGIN{
do
{
sum+=i
i++
}
while (i<=100)
print sum
}
[root@hbs ~]# awk -f do_while.sh
5050
[root@hbs ~]#
-F 指定分割符
[root@hbs ~]# awk 'BEGIN{FS=":"}{print $1}' /etc/passwd
root
bin
……
sshd
postfix
[root@hbs ~]#
[root@hbs ~]# awk -F ":" '{print $1}' /etc/passwd
root
bin
daemon
……
sshd
postfix
[root@hbs ~]#
-V 查看awk 版本號
[root@hbs ~]# awk -V
GNU Awk 4.0.2
Copyright (C) 1989, 1991-2012 Free Software Foundation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/.
[root@hbs ~]#
- 關於awk 的用法,其實還有很多,包括後面的awk數組中用法等等,如果感興趣的話,您可以留言,大家一起研究awk編程的內容