+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
張賀,多年互聯網行業工做經驗,擔任過網絡工程師、系統集成工程師、LINUX系統運維工程師
我的網站:www.zhanghehe.cn
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-linux
AWK
的內容也太多了,簡單的作一個複習,都差點閃了老腰!nginx
我理解的awk
的做用就是取列和取列並計算,當咱們一想到取列或者取列計算的時候就應當立馬想到 awk
,另外,awk
還至關不要臉的包攬了它二弟和它三弟的部分工做,讓我非常焦灼,在使用的時候不知道用哪一個好!正則表達式
AWK
的用戶與sed
的用法類似,它的語法是這樣的:centos
awk <選項> '找誰{幹啥}' #必定要注意引號是英文的單引號
awk
的選項其實比較少,經常使用就是-F
,用來指定分隔符,最有亮點的地方是分隔符居然能夠指定多個!!!bash
//大於號能夠換成大於、大於等於、小於、小於等於,等於 [root@centos7 ~]# awk 'NR>=2{print}' /etc/passwd // 打印出第三行的第二列 //awk默認以一個或連續多個空格,TAB,連續多個TAB爲分隔符,因此這裏面不指定分隔符,默認就是以空格爲分隔符的。 ip a s ens33 | awk 'NR==3{print $2}' 192.168.80.200/24 ifconfig eth0 | awk 'NR==2{print $2}' 192.168.80.2 //指定使用空格和斜線爲分隔符,指定多個分隔符,並指定了次數,一次或屢次,也就說使用了[]以後,連續之意失效了,須要手動經過擴展的正則表達式加號強調。 [root@centos7 ~]# ip a s ens33 | awk ‐F'[ /]+' 'NR==3{print $3}' 192.168.80.200
使用awk的注意點:網絡
2、行與列
必定要用單引號,三劍客最好都要使用單引號,否則會出各類奇怪的事情!app
分隔符能夠指定多個,若是不指定的的話,默認就是以空格或連續的空格,TAB或 者連續的TAB爲分隔符的。less
awk的選項使用的很少,最經常使用的選項就是指定分隔符,即-F的選項,偶爾會用 到-v OFS,不過不多。運維
「幹啥」的選項也比較少,最經常使用的也就是p,即print打印,默認就是print打 印。ide
awk原本就支持擴展的正則表達式,無需像sed同樣加r
NR
是number is recored
的縮寫,其實就是行號的意思,如上面 的例子所示。
$0
表明的是一整行,$1
表明的就不是第一行了,$1
表明的就是第一列,其實咱們把$0
理解成全部列就很天然了,END
表明的最後一列,咱們下面有例子。
//若是不指定是第一行NR==1,它默認就會把文件裏面的第一列所有給你打印出來 [root@centos7 ~]# awk ‐F':' 'NR==1{print $0}' /etc/passwd root:x:0:0:root:/root:/bin/bash //END表明最後一行,打印最後一行,{print $0}是默認的,即便不寫,效果也是同樣的。 [root@centos7 ~]# awk 'END{print $0}' /etc/passwd zhanghe:x:1000:1000:zhanghe:/home/zhanghe:/bin/bash //你看,不加'$0',效果是同樣的,END(print $0) 至關於 END (print) [root@centos7 ~]# awk 'END{print}' /etc/passwd zhanghe:x:1000:1000:zhanghe:/home/zhanghe:/bin/bash #sed ‐n '$p sed也能夠實現這樣的效果
那若是我想要第2行之後的行呢?就正常寫就行,以下
1 [root@centos7 ~]# awk 'NR>=2{print}' /etc/passwd
行號也能夠單獨的使用,好比我想顯示出/etc/passwd
的行號,也就說想要實現cat -n /etc/passwd
和less -N /etc/passwd
的功能
[root@centos7 ~]# awk '{print NR}' /etc/passwd #這樣僅把全部的行號打印出來了 1 2 3 4 …… //在行號後面再加一個$0,$0啥意思還記得嗎?表明全部列,行號加上顯示全部列就會有cat ‐n的效果了。 [root@centos7 ~]# awk '{print NR,$0}' /etc/passwd 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
其實,sed
能作取行操做,awk
也能作,好比:
1 [root@centos7 ~]# sed ‐n 2p /etc/passwd #打印第二行 2 bin:x:1:1:bin:/bin:/sbin/nologin 3 [root@centos7 ~]# awk 'NR==2{print}' /etc/passwd #打印第二行 4 bin:x:1:1:bin:/bin:/sbin/nologin
上述例子當中的「$數字」的意思其實就是取哪一列,‘print $3’其實就是取第3列,若是 咱們想取多列呢?好比我想取出/etc/passwd
文件文件當中第1列和第3列,怎麼搞呢?
//取最後一行的第一列和最後三列 [root@centos7 ~]# awk ‐F':' 'END{print $1,$3}' /etc/passwd zhanghe 1000
那若是咱們想取最後一列呢?咱們知道END表明最後一行,最後一列用NF來表示,以下所 示:
1 [root@centos7 ~]#awk -F':' 'END{print $NF}' /etc/passwd 2 /bin/bash
取最後一列,會用到什麼地方呢?好比,日誌文件,/var/log/secure
文件下的日誌的長度並非固定的,在取日誌記錄的最後一部分的時候,咱們能夠用到取最後一列。 那取倒數第二列呢?
1 [root@centos7 ~]# awk ‐F':' 'NR==1{print $NF‐1}' /etc/passwd #這樣寫不行,須要加上一個括號,以下所示: 2 ‐1 3 [root@centos7 ~]# awk ‐F':' 'NR==1{print $(NF‐1)}' /etc/passwd 4 /root 5 [root@centos7 ~]# echo 66 77 88 | awk '{print $NF‐1}' 6 87 7 [root@centos7 ~]# echo 66 77 88 | awk '{print $(NF‐1)}' 8 77
其實取列的時候還能夠進行比較呢?好比 ,我想要找到/etc/passwd
當中第三列大於500的 行。
1 [root@centos7 ~]# awk ‐F':' '$3>500{print $0}' /etc/passwd #後面的{print$0}是能夠省略的。3、取磁盤的使用率--案例
案例一:顯示磁盤使用率大於10%的分區和掛載點
[root@centos7 ~]# df ‐h | awk '$5>10%' #列比較的時候不能識別%號 awk: cmd. line:2: $5>10% awk: cmd. line:2: ^ unexpected newline or end of string [root@centos7 ~]# df ‐h | awk '$5>10' #不加%,會不許,你看,下面把8%的也顯示 出來了,下面有解釋 文件系統 容量 已用 可用 已用% 掛載點 /dev/mapper/centos_centos7‐root 50G 3.9G 47G 8% / /dev/sda1 1014M 179M 836M 18% /boot [root@centos7 ~]# df ‐h | sed 's@%@@g' | awk '$5>10{print $1,$NF}' #經過sed把%全都刪除 文件系統 掛載點 /dev/sda1 /boot [root@centos7 ~]# df ‐h | sed 's@%@@g' | awk '$5>10{print $1,$NF}' | tai l ‐1 #這樣的結果就正常了。 /dev/sda1 /boot
爲何會出現不許的狀況?其實並非不許,LINUX系統不會騙咱們的,只不過,它默認不是按照咱們覺得的方式在比大小,以下所示:
[root@centos7 ~]# seq 10 #生成10個數 1 2 3 4 5 6 7 8 9 10 [root@centos7 ~]# seq 10 | sort #使用sort對它們進行排序,結果2比10大?這是怎麼回事?是由於linux在比較大小的時候默認是按位進行比較的, 13 1 14 10 15 2 16 3 17 4 18 5 19 6 20 7 21 8 22 9 23 [root@centos7 ~]# seq 10 | sort ‐n #加一個‐n的參數,就是按照數字的大小進行排序,你看,這又恢復正常了。 24 1 25 2 26 3 27 4 28 5 29 6 30 7 31 8 32 9 33 10
若是問題再難一點,顯示出磁盤使用率大於10%且小於50%的磁盤分區和掛載點呢?就用 &&符號就行,&&就是而且的意思嘛!以下所示:
1 [root@centos7 ~]# df ‐h | sed 's@%@@g' | awk '$5>10&&$5<50{print $1,$NF}' | tail ‐1 2 /dev/sda1 /boot
咱們在看行的時候也可使用,咱們咱們想看第三行到第六行中間的行:
1 [root@centos7 ~]# awk 'NR>3&&NR<6{print NR,$0}' /etc/passwd 2 4 adm:x:3:4:adm:/var/adm:/sbin/nologin 3 5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin 1 [root@centos7 ~]# sed ‐n '4,5p' /etc/passwd 2 adm:x:3:4:adm:/var/adm:/sbin/nologin 3 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin4、正則表達式
作爲條件咱們上面在描述條件的時候都是用的行號,其實咱們還可使用正則表達式作爲條件。 好比1:過濾出包含數字的行
1 [root@centos7 test.dir]# cat test.txt 2 zhanghe 3 zhanghe6 4 [root@centos7 test.dir]# awk '/[0‐9]/' test.txt #awk在使用正則表達式作爲條件的時候要用//號的,sed也是這樣,完整的寫法是這樣的'/[0‐9]/{print $0}' 5 zhanghe6 6 [root@centos7 test.dir]# grep '[0‐9]' test.txt 7 zhanghe6
好比2:過濾出/etc/passwd
當中開頭是root
一直到結尾是shutdown
之間的行
[root@nginx ~]# sed -n '/^root/,/shutdown$/p' /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 adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown [root@nginx ~]# awk '/^root/,/shutdown$/' /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 adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
好比3:過濾出/etc/passwd
當中開關是root
一直到結尾是shutdown
之間的行的最後一列
[root@nginx ~]# awk -F: '/^root/,/shutdown$/ {print $NF}' /etc/passwd /bin/bash /sbin/nologin /sbin/nologin /sbin/nologin /sbin/nologin /bin/sync /sbin/shutdown
好比4:顯示出最後一列是bash的用戶名,下面這個最是騷氣,直接指定去匹配哪個列
1 [root@centos7 ~]# awk ‐F':' '$NF~/bash$/{print $1}' /etc/passwd 2 root 3 zhanghe5、範圍作爲條件
好比1:顯示以一個z或者一個r開頭的用戶名
1 [root@centos7 ~]# awk ‐F':' '$1~/^(r|z)/{print $1}' /etc/passwd #也能夠這樣寫:awk ‐F':' '$1~/^[rz]/{print $1}' 2 root 3 rpc 4 rtkit 5 radvd 6 rpcuser 7 zhanghe
注意:^在grep
和sed
當中只能表示以什麼什麼開頭的行,在awk
當中能夠經過前而的列表示某一列當中以什麼開頭的行,也就是說範圍增長了。 好比2:顯示UID號碼最爲一位是1或是5的全名
1 [root@centos7 ~]# awk ‐F':' '$3~/[15]$/{print $1}' /etc/passwd 2 bin 3 sync 4 operator 5 dbus 6 pulse 7 radvd 8 unbound 9 setroubleshoot 1 [root@centos7 ~]# awk ‐F':' '{print $3,$4}' /etc/passwd | head ‐4 2 0 0 3 1 1 4 2 2 5 3 4 6 [root@centos7 ~]# awk ‐F':' '{print "#"$3"#"$4}' /etc/passwd | head ‐4 #能夠在裏面加點東西,要用雙引號才能夠,雙引號裏面有什麼,就會原封不動的顯示什麼。 7 #0#0 8 #1#1 9 #2#2 10 #3#4
用awk作sed的替換功能 用gsub函數,用法:{gsub (/????,"$")} 將雙豎線的內容替換爲雙引號裏面的內容
1 [root@centos7 ~]# awk '{gsub (/:/,"$");print}' /etc/passwd | head ‐4 2 root$x$0$0$root$/root$/bin/bash 3 bin$x$1$1$bin$/bin$/sbin/nologin 4 daemon$x$2$2$daemon$/sbin$/sbin/nologin 5 adm$x$3$4$adm$/var/adm$/sbin/nologin 1 [root@centos7 ~]# awk '{gsub (/r/,"R") $1;print}' /etc/passwd | head ‐4 #精確替換哪一列的什麼 2 Root:x:0:0:Root:/Root:/bin/bash 3 bin:x:1:1:bin:/bin:/sbin/nologin 4 daemon:x:2:2:daemon:/sbin:/sbin/nologin 5 adm:x:3:4:adm:/vaR/adm:/sbin/nologin 6 [root@centos7 ~]# awk '{gsub (/:/,"$");print}' /etc/passwd | head ‐4 #不指定哪一列就是一整行,至關於$0,也就是全部列 7 root$x$0$0$root$/root$/bin/bash 8 bin$x$1$1$bin$/bin$/sbin/nologin 9 daemon$x$2$2$daemon$/sbin$/sbin/nologin 10 adm$x$3$4$adm$/var/adm$/sbin/nologin
顯示人名和UID,而後以逗號分隔,就用最簡單的方式便可
1 [root@centos7 ~]# awk ‐F':' '{print $1,$3}' /etc/passwd | head ‐4 2 root 0 3 bin 1 4 daemon 2 5 adm 3 6 [root@centos7 ~]# awk ‐F':' '{print $1","$3}' /etc/passwd | head ‐4 7 root,0 8 bin,1 9 daemon,2 10 adm,36、BEGIN和END
記住:
1. BEGIN裏面的內容會在awk讀取文件以前執行,通常來用計算。
2. END裏面的內容會有awk讀取文件以後執行,通常用來作統計。
BEGIN:
1 [root@centos7 ~]# awk 'BEGIN{print 1+2,1‐8}' 2 3 ‐7 3 [root@centos7 ~]# awk ‐F':' 'BEGIN{OFS="$$$"}{print $1,$2}' /etc/passwd | head ‐4 #也能夠用來修改變量,至關於上面講的‐v OFS 4 root$$$x 5 bin$$$x 6 daemon$$$x 7 adm$$$x
END: 何時用END?統計的時候,先進行計算,最後END()顯示最後結果,其實這纔是 awk最重要的功能,awk原名文本報名生成器,用來生成報告用的,生成報告的話必定會用 到統計了。
統計/etc//services 文件當中空行的數量 i=i+1 至關於i++ 用來出現的總次數,初始值是0.
1 [root@centos7 tmp]# awk '/^$/{i++;print i}' /tmp/test.sh #有5個空行,這不是我想要的結果 2 1 3 2 4 3 5 4 6 5
1 [root@centos7 tmp]# awk '/^$/{i++}END{print i}' /tmp/test.sh #完成以後再打開出變量i,這裏的變量i已經增加到5了,這時候打印出來正合適呢! 2 5
求和:i=i+$,至關於i+=$
和:i=i+$,至關於i+=$ 1 [root@centos7 tmp]# cat test.txt 2 12 3 11 4 14 5 [root@centos7 tmp]# awk '{sum += $1};END{print sum}' test.txt #對第一列進行求和 6 37 1 [root@centos7 tmp]# cat test.txt 2 12 45 3 11 11 4 14 13 5 [root@centos7 tmp]# awk '{sum += $2};END{print sum}' test.txt #對第二列進行求和 6 69 1 [root@centos7 tmp]# cat test.txt 2 aaa 12 45 3 aaa 11 11 4 aaa 14 13 5 bbb 1 2 6 [root@centos7 tmp]# awk '/aaa/{sum += $3}END{print sum}' test.txt #對符號條件的行進行求和 7 69
//補充 ifconfig eth0 | sed 's@^[[:space:]]\+@@g' | awk '/^inet/{ print $2}' | head -1 192.168.80.9