awk在CentOS操做系統中是一個軟連接,連接到gawk程序上的。awk主要是對文件的行進行操做,將一行按照指定的方式進行切割。node
1、awk工做機制nginx
awk在處理文本流時,每一次會讀取文本流中的一行並對這一行按指定的分隔符進行分隔,分隔後能夠對每個字段進行處理,其中輸入的分隔符能夠和輸出的分隔符不同,這些都是經過awk內置的變量來處理的。web
2、awk命令運用正則表達式
格式:awk [OPTIONS] 'program' FILE1 FILE2 ...shell
2.1 printexpress
用法:print item1,item2,….vim
示例1:輸出/etc/passwd文件中的第1個字段和第3個字段的值centos
[root@node-3 ~]# awk -F: '{print $1,$3}'/etc/passwd root 0 bin 1 daemon 2 adm 3
根據輸出結果進行分析:數組
(1)-F:用於指明輸入字段的分隔符bash
(2)每一個item之間用逗號分隔,輸出時的分隔符爲空白字符;
(3)若是print在輸出時省略了item,將會輸出整行的內容
示例2:根據上示例的要求,進行以「Name:root,UID:0」的格式輸出
[root@node-3 ~]# awk -F: '{print"Name:"$1,",UID:"$3}' /etc/passwd Name:root ,UID:0 Name:bin ,UID:1 Name:daemon ,UID:2
根據輸出結果進行分析:
(1)在各item中以「」引號的內容將會原樣的輸出
(2)數值會被隱式轉換爲字符串進行輸出
2.2 awk變量
awk的變量有內建變量和自定義的變量,內建變量是awk事先就已經定義好了,直接使用變量名就能夠了,自定義變量根據狀況的需求進行定義。
2.2.1 自定義變量
格式:-v VAR_NAME=VALUE
示例:[root@node-3 ~]# awk -v file="abc""{print file}" /etc/passwd abc abc abc
根據輸出結果進行分析:
(1)-v用於自定義變量,變量名區別大小寫,遵循變量的定義
(2)顯示變量的值直接寫上變量名
(3)示例中將輸出屢次,次數是根據/etc/passwd的行數來決定的
2.2.2 內建變量
變量名 | 說明 |
FS |
輸入字段分隔符,默認爲空白; |
RS | 輸入時的行分隔符,默認爲換行符; |
OFS | 輸出時的字段分隔符,默認爲空白字符; |
ORS | 輸出時的行分隔符,默認爲換行符; |
NF | 當前行的字段數; |
NR | 行數;命令後跟的全部文件將統一計數; |
FNR | 行數,多個文件時,各文件單獨計數; |
FILENAME | 當前正被awk讀取的文件的文件名; |
ARGC | awk命令行中的參數的個數; |
ARGV | 數組,保存了命令行參數自己; |
示例1:顯示/etc/passwd文件中以「:」和「/」分隔符的第1個字段和第7個字段,原文件以下:
[root@node-3 ~]# cat /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin
[root@node-3 ~]# awk -v FS="[:/]"'{print $1,$7}' /etc/passwd root root bin bin daemon sbin
根據輸出結果進行分析:
(1)-v:對變量進行賦值,包含內建變量和自定義變量;
(2)FS是awk的內建變量,表示指定字符之間的分隔符;
(3)FS的值要用雙引號引發來,若是要指定多個分隔直接寫在「[]」中便可。
示例2:測試文件以下,以「,」爲行結束符,輸出整行的內容,接着輸出第1字段、第3字段:
[root@node-3 ~]# cat awk.txt how are you , how old are you ? how old your , Yes are you ? [root@node-3 ~]# awk -v RS=","'{print $0}' awk.txt how are you howold are you ? how old your Yesare you ? [root@node-3 ~]# awk -v FS=" " -v RS="," '{print $1,$3}' awk.txt how you how are Yes you
根據輸出結果進行分析:
(1)RS改變了行結束符,默認的行結束符可使用cat -A awk.txt查看。
(2)-v選項可使用屢次,每定義一個變量的值,要使用一次「-v」選項。
示例3:根據/etc/passwd文件中輸出第1字段和第3字段,格式爲「root:0」,原文件以下:
[root@node-3 ~]# cat /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin
方法1: [root@node-3 ~]# awk -F: -v OFS=":" '{print $1,$3}'/etc/passwd root:0 bin:1 daemon:2 方法2: [root@node-3 ~]# awk -F: '{print $1":"$3}' /etc/passwd root:0 bin:1 daemon:2
根據輸出結果進行分析:
(1)-v OFS=」:」用於定義輸出字段之間的分隔符,默認爲空白字符
(2)方法2中的 pirnt $1」:」$3,中的雙引號中的內容會原樣的輸出,這就是字符串之間的鏈接
示例4:將示例3中的輸出結果以「,」會換行符。
[root@node-3 ~]# awk -F: -vORS="," '{print $1":"$3}' /etc/passwd root:0,bin:1,daemon:2,[root@node-3 ~]#
根據輸出結果進行分析:
(1)ORS更改默認的換行符將以指定符號輸出
示例5:根據以下文件內容,輸出字段的個數,並顯示最後一個字段的內容
[root@node-3 ~]# cat awk.txt how are you , how old are you ? how old your , Yes are you ? [root@node-3 ~]# awk '{print NF,$NF}'awk.txt 9 ? 8 ?
根據輸出結果進行分析:
(1)NF使用顯示被分隔符分隔後的字段個數。
(2)$後面跟上一個數字用於顯示指定字段的內容,而NF是一個數字,替換後就是顯示最後一個字段。
示例6:顯示awk.txt和/etc/passwd文件行號
[root@node-3 ~]# awk '{print NR,$0}'awk.txt /etc/passwd 1 how are you , how old are you ? 2 how old your , Yes are you ? 3 root:x:0:0:root:/root:/bin/bash 4 bin:x:1:1:bin:/bin:/sbin/nologin 5 daemon:x:2:2:daemon:/sbin:/sbin/nologin [root@node-3 ~]# awk '{print FNR,$0}'awk.txt /etc/passwd 1 how are you , how old are you ? 2 how old your , Yes are you ? 1 root:x:0:0:root:/root:/bin/bash 2 bin:x:1:1:bin:/bin:/sbin/nologin 3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
根據輸出結果進行分析:
(1)awk後能夠跟多個文件
(2)NR變量在對多個文件顯示行號時,後一個文件的行號是接着前一個文件的行號繼續增長顯示的
(3)FNR變量對多個文件是分別進行顯示行號
示例7:顯示awk當前正在處理的文件名
[root@node-3 ~]# awk '{print FNR,FILENAME}'awk.txt /etc/passwd 1 awk.txt 2 awk.txt 1 /etc/passwd 2 /etc/passwd 3 /etc/passwd
示例8:根據示例7顯示awk的參數個數及第2個參數的值
[root@node-3 ~]# awk '{printFNR,FILENAME,ARGC,ARGV[1]}' awk.txt /etc/passwd 1 awk.txt 3 awk.txt 2 awk.txt 3 awk.txt 1 /etc/passwd 3 awk.txt 2 /etc/passwd 3 awk.txt 3 /etc/passwd 3 awk.txt
根據輸出結果進行分析:
(1)ARGC用於保存當前awk參數的個數
(2)ARGV是一個數組,保存的是當前數組每一個參數的值,數組的Index號是從0開始編號的,ARGV[0]存放的是awk, ARGV[1]存放的是awk.txt, ARGV[2]存放的是/etc/passwd,ARGV[3]存放的是NULL。
2.3 printf
printf用於格式化輸出,此風格相似於C語言中的格式化輸出信息,能夠根據定義在指定的位置顯示字段信息及保留小數點後指定的位數等 。
格式:printf FORMAT,item1,item2,...
類型 | 符號 | 說明 |
格式符 | %c | 顯示字符的ASCII碼; |
%d,%i | 顯示爲十進制整數; | |
%e,%E | 科學計數法顯示數值; | |
%f | 顯示爲浮點數; | |
%g,%G | 以科學計數法或浮點數格式顯示數值; | |
%s | 顯示爲字符串; | |
%u | 顯示無符號整數; | |
%% | 顯示%符號自身; | |
修飾符 | #[.#] | 左邊的#指用於指定顯示寬度;右邊的#指顯示精度; |
+ | 顯示數值符號 | |
- | 左對齊,默認爲右對齊 |
注意:
(1) 必須提供FORMAT;
(2) 與print語句不一樣,printf不會自動換行,須要顯式指定換行符:\n
(3) FORMAT中須要分別爲後面的每一個item指定一個格式符,不然item則沒法顯示;
示例:將/etc/passwd文件進行格式化輸出
[root@node-3 ~]# awk -F: '{printf"%20s:%-10.5f:%s\n",$1,$3,$NF}' /etc/passwd root:0.00000 :/bin/bash bin:1.00000 :/sbin/nologin daemon:2.00000 :/sbin/nologin [root@node-3 ~]# awk -F: '{printf"%20s:%10.5f:%s\n",$1,$3,$NF}' /etc/passwd root: 0.00000:/bin/bash bin: 1.00000:/sbin/nologin daemon: 2.00000:/sbin/nologin
根據輸出結果進行分析:
(1)%20s:輸出的是字符串,第1個字段的長度爲20,awk默認是右對齊
(2)%10.5f:輸出的是浮點型數值,長度是10,小點後面保留5位
(3)%-10.5f:其中的「-」表示左對齊
(4)\n:表示換行符
(5)FORMAT中除格式符和修飾符以外的其它符號或字符都將原樣的輸出
2.4 操做符
awk的操做符很是的豐富,包含算術操做符、字符操做符、賦值操做符、比較操做符、模式匹配操做符、邏輯操做符、條件表達式等。
類型 | 符號 | 說明 |
算術操做符 | x+y, x-y, x*y, x/y, x^y, x%y,-x,+x | 加、減、乘、除、次方、模,負值、轉換爲數值 |
賦值操做符 | =, +=, -=, *=, /=, %=,++, -- | 賦值、加後賦值、減後賦值、乘後賦值、除後賦值、取模後賦值、自增、自減 |
比較操做符 | >, >=, <, <=, ==, != | 大於、大於等於、小於、小於等於、等於、不等於 |
模式匹配操做符 | ~,!~ |
是否能由右側指定的模式所匹配;是否不能由右側指定模式所匹配; |
邏輯操做符 | &&,|| | 與運算、或運算 |
條件條件式 | selector?if-true-expression:if-false-expression | 條件表達式 |
示例1:顯示/etc/passwd文件UID大於500的用戶
[root@node-3 ~]# awk -F: '$3>500{print$1,$3}' /etc/passwd nfsnobody 65534 testuser 1000 centos 1001 user1 1002 gentoo 1003
示例2:顯示/etc/passwd文件中每行字段中包含有bash字符的行
[root@node-3 ~]# awk -F:'$0~"bash"{print $0}' /etc/passwd root:x:0:0:root:/root:/bin/bash bbs:x:496:493::/home/bbs:/bin/bash testuser:x:1000:500::/home/testuser:/bin/bash centos:x:1001:1001::/home/centos:/bin/bash user1:x:1002:1002:chrootuser:/home/user1:/bin/bash gentoo:x:1003:1003::/home/gentoo:/bin/bash nginx:x:495:492::/home/nginx:/bin/bash
示例3:判斷用戶UID是否大於等於500,格式化顯示用戶名信息
[root@node-3 ~]# awk -F: '$3>=500?type="commonuser":type="system user"{printf "%20s:%s\n",$1,type }'/etc/passwd ……………省略………………… testuser:common user centos:common user user1:common user gentoo:common user nginx:system user
根據輸出結果進行分析:
(1)$3>=500?type="commonuser":type="system user":將/etc/passwd文件中以「:」爲分隔符第3段值取出來,若是UID大於等於500把變量type賦值systemuser,不然就把變量type賦值system user.
(2)使用格式化顯示用戶名和type變量的值
2.5 PATTERN
在PATTERN中可使用正則表達式,關係表達式,指定要處理的行範圍等等 。
PATTERN | 說明 |
Empty | 空模式,匹配全部行; |
/Regular Expression/ | 僅將ACTION應用於可以被Regular Expression(正則表達式)所匹配到的行; |
relational expression | 關係表達式,即結果爲「真」、「假」的表達式,或者其結果能類同於「真」或「假」的表達;通常來講,其結果爲非0數值或非空字符串便可類同爲「真」,不然,則類同爲「假」; |
line ranges | 行範圍,相似sed或vim中的地址定界方式; |
BEGIN | 在文件格式化操做開始以前事先執行的一次操做;一般用於輸出表頭或作出一個預處理操做; |
END | 在文件格式操做完成以後,命令退出以前執行的一次操做;一般用於輸出表尾或作出清理操做; |
示例1:在/etc/passwd文件中顯示以bash結尾的行
[root@node-3 ~]# awk -F: '/bash$/{print$0}' /etc/passwd root:x:0:0:root:/root:/bin/bash bbs:x:496:493::/home/bbs:/bin/bash testuser:x:1000:500::/home/testuser:/bin/bash centos:x:1001:1001::/home/centos:/bin/bash user1:x:1002:1002:chrootuser:/home/user1:/bin/bash gentoo:x:1003:1003::/home/gentoo:/bin/bash nginx:x:495:492::/home/nginx:/bin/bash
示例2:在/etc/passwd文件中顯示UID大於500的用戶名
[root@node-3 ~]# awk -F: '$3>500{print$1}' /etc/passwd nfsnobody testuser centos user1 gentoo
示例3:統計/etc/passwd文件中全部UID的和
[root@node-3 ~]# awk 'BEGIN{FS=":";sum=0}{sum+=$3}END{print sum}' /etc/passwd 73318
根據輸出結果進行分析:
(1)BEGIN{FS=":";sum=0}:表示在awk在對行處理以前執行的動做,FS是指定字段的分隔符,sum是自定義的一個變量,用於累加全部UID的和
(2){sum+=$3}:就是在對每一行進行操做,這裏沒有使用print輸出信息,sum=sum+$3;
(3)END{print sum}:awk對文件中全部行處理完以後在執行END的語句
示例4:格式化輸出/etc/passwd文件中用戶和UID
[root@node-3 ~]# awk -F: 'BEGIN {printf"%15s:%-s\n","User","UID";print"================================="}{printf"%15s:%-s\n",$1,$3}END{print"================================";printf "%20s\n","ENDof file"}' /etc/passwd User:UID ================================= root:0 bin:1 daemon:2 adm:3 lp:4 sync:5 …………………省略……………… user1:1002 gentoo:1003 nginx:495 ================================ END of file
2.6 控制語句
在awk控制語句中有if、while、do、for、switch、break、contiune、next等
2.6.1 if-else語句
格式:if (condition) {statements} [else{statements}]
示例1:在/etc/passwd文件中顯示UID大於500的用戶名
[root@node-3 ~]# awk -F:'{if($3>500){print $1,$3}}' /etc/passwd nfsnobody 65534 testuser 1000 centos 1001 user1 1002 gentoo 1003
示例2:判斷/etc/inittab的字段數大於6的,以空格分隔的
[root@node-3 ~]# awk '{if (NF>6) {printNF,$0}}' /etc/inittab 11 # inittab is only used by upstart forthe default runlevel. 12 # ADDING OTHER CONFIGURATION HERE WILLHAVE NO EFFECT ON YOUR SYSTEM. 7 # System initialization is started by/etc/init/rcS.conf 7 # Individual runlevels are started by/etc/init/rc.conf 9 # Terminal gettys are handled by/etc/init/tty.conf and /etc/init/serial.conf, 12 # For information on how to writeupstart event handlers, or how 8 # upstart works, see init(5), init(8),and initctl(8). 7 # Default runlevel. The runlevels usedare: 10 # 0 - halt (Do NOT set initdefault to this) 16 # 2 - Multiuser, without NFS (The same as 3, if you do not havenetworking) 10 # 6 - reboot (Do NOT set initdefault to this)
2.6.2 while循環
格式:while (condition) {statements}
示例:顯示字段字符數大於10的字符
[root@node-3 ~]# awk '{i=1;while(i<NF){if (length($i)>10) printf "%20s:%d\n",$i,length($i);i++}}'/etc/inittab CONFIGURATION:13 initialization:14 Ctrl-Alt-Delete:15 /etc/init/tty.conf:18 configuration:13 information:11 initdefault:11 initdefault:11
根據輸出結果進行分析:
(1)while用於在當前行的種字段之間進行循環。
(2)length()是awk的內置變量,用於測試字符在長度的
2.6.3 for循環
格式:for (expr1;expr2;expr3) {statements}
示例:顯示/etc/inittab文件中以空格爲分隔符,顯示每一個字段的長度
[root@node-3 ~]# awk '{for(i=1;i<=NF;i++) {printf "%20s:%d\n",$i,length($i)}}' /etc/inittab #:1 inittab:7 is:2 only:4 used:4 by:2
2.6.4 bread 和countinue
break [n]:退出當前循環,n是一個數字,用於指定退出幾層循環;
continue:提早結束本輪循環而進入下一輪;
示例:顯示/etc/passwd每一個字段的字符數小於10的,只要遇到大於10的就不在判斷後面的字段的字符數
[root@node-3 ~]# awk -F:'{for(i=1;i<=NF;i++){if(length($i)>10){break}else {printlength($i),$i}}}' /etc/passwd 4 root 1 x 1 0 1 0 4 root 5 /root 9 /bin/bash 3 bin 1 x 1 1 1 1
2.6.5 next
next用於提早結束對本行文本的處理,而提早進入下一行的處理操做;
示例:顯示/etc/passwd中UID是奇數的用戶名和UID
[root@node-3 ~]# awk -F: '{if($3%2==0)next;print $1,$3}' /etc/passwd bin 1 adm 3 sync 5 halt 7 operator 11 gopher 13 nobody 99
2.7 數組
格式:array[index-expression]
其中index-expression能夠是任意字符,若是某數組元素事先不存在,則在引用時,awk會自動建立元素並將其值初始化爲空串,awk的數組下標是從1開始編號的。
若是要遍歷數組中的元素,則要使用for (var_name in array)
示例:統計當前系統上全部tcp鏈接的各類狀態的個數;
[root@node-3 ~]# netstat -tan|awk '/^tcp/{count[$NF]++}END{for(i incount){print i,count[i]}}' TIME_WAIT 4000 ESTABLISHED 2 LISTEN 8
示例:統計指定的web訪問日誌中各ip的資源訪問次數:
[root@node-3 ~]# awk '{ip[$1]++}END{for (iin ip){print i,ip[i]}}' /var/log/httpd/access_log 172.16.9.35 4016 172.16.9.7 186 172.16.9.9 153
2.8 函數
在awk中函數有內建函數和用戶自定義函數兩種。
2.8.1 內建函數
函數名 | 說明 |
rand() | 返回0至1之間的一個隨機數; |
length([s]) | 返回指定的字符串的長度; |
sub(r,s[,t]) | 基於r所表示的模式來匹配字符串t中的內容,將其第一次被匹配到的內容替換爲s所表示的字符串; |
gsub(r,s[,t]) | 基於r所表示的模式來匹配字符串t中的內容,將其全部被匹配到的內容均替換爲s所表示的字符串; |
split(s,a[,r]) | 以r爲分隔符去切割字符串s,並將切割後的結果保存至a表示的數組中; |
substr(s,i[,n]) | 從s所表示的字符串中取子串,取法:從i表示的位置開始,取n個字符; |
systime() | 取當前系統時間,結果形式爲時間戳; |
示例1:返回一個0至1之間的一個隨機數
[root@node-3 ~]# awk 'BEGIN {print rand()}' 0.237788
示例2:返回/etc/passwd文件中用戶名字符串的長度
[root@node-3 ~]# awk -F: '{print$1,length($1)}' /etc/passwd root 4 bin 3 daemon 6 adm 3
示例3:將root用戶名中「oo」替換成大寫的「OO」
[root@node-3 ~]# awk -F:'/^root/{sub("oo","OO",$0);print $0}' /etc/passwd rOOt:x:0:0:root:/root:/bin/bash
示例4:將以root用戶名爲行的所有「oo」替換成大寫的「OO」
[root@node-3 ~]# awk -F:'/^root/{gsub("oo","OO",$0);print $0}' /etc/passwd rOOt:x:0:0:rOOt:/rOOt:/bin/bash
示例5:split函數指明字段的分隔符
[root@node-3 ~]# awk '{split($0,user,":");printuser[1]}' /etc/passwd root bin daemon adm
示例6:在/etc/passwd文件中默認shell是/bin/bash的用戶,從第7個字段中從4個字符開始取出3個字符
[root@node-3 ~]# awk -F:'/bash$/{char=substr($NF,4,3);printf "%s:%5s\n",$NF,char}'/etc/passwd /bin/bash: n/b /bin/bash: n/b /bin/bash: n/b /bin/bash: n/b /bin/bash: n/b /bin/bash: n/b /bin/bash: n/b
若是想獲取更多的幫助請man awk.