文本三劍客之AWKlinux
AWK是一種優良的文本處理工具。它不只是 Linux中也是任何環境中現有的功能最強大的數據處理引擎之一。這種編程及數據操做語言(其名稱得自於它的創始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首個字母)的最大功能取決於一我的所擁有的知識。AWK 提供了極其強大的功能:能夠進行樣式裝入、流控制、數學運算符進程控制語句甚至於內置的變量和函數。它具有了一個完整的語言所應具備的幾乎全部精美特性。實際上 AWK 的確擁有本身的語言:AWK 程序設計語言, 三位建立者已將它正式定義爲「樣式掃描和處理語言」。它容許您建立簡短的程序,這些程序讀取輸入文件、爲數據排序、處理數據、對輸入執行計算以及生成報表,還有無數其餘的功能。git
awk是一個強大的文本分析工具,與grep(查找)、sed(編輯)一併稱爲「文本處理三劍客」。awk最強大的功能是對數據分析並生成報告。web
awk有3個不一樣版本: awk、nawk和gawk,未做特別說明,通常指gawk,gawk是AWK的GNU版本。shell
第一步:執行BEGIN{action;… }語句塊中的語句 express
第二步:從文件或標準輸入(stdin)讀取一行,而後執行pattern{ action;… }語句塊,它逐行掃描文件,從第一行到最後一行重複這 個過程,直到文件所有被讀取完畢。 apache
第三步:當讀至輸入流末尾時,執行END{action;…}語句塊 編程
BEGIN語句塊在awk開始從輸入流中讀取行以前被執行,這是一個 可選的語句塊,好比變量初始化、打印輸出表格的表頭等語句一般 能夠寫在BEGIN語句塊中 centos
END語句塊在awk從輸入流中讀取完全部的行以後即被執行,好比 打印全部行的分析結果這類信息彙總都是在END語句塊中完成,它 也是一個可選語句塊數組
pattern語句塊中的通用命令是最重要的部分,也是可選的。若是 沒有提供pattern語句塊,則默認執行{ print },即打印每個讀取 到的行,awk讀取的每一行都會執行該語句塊
bash
分割符、域和記錄
awk執行時,由分隔符分隔的字段(域)標記$1,$2..$n稱 爲域標識。$0爲全部域,注意:和shell中變量$符含義不一樣
文件的每一行稱爲記錄
省略action,則默認執行 print $0 的操做
步驟
執行BEGIN{action;…}
BEGIN在輸入以前執行,一般用來打印表頭,變量初始化。
讀取,執行pattern{action;…}
默認執行{ print }
執行END{action;…}
讀取到打印結束後執行,一般用做分析結果,信息彙總
AWK語法基本格式:
基本格式:awk [options] 'program' file…
選項[options]:
-F 指明輸入時用到的字段分隔符
-v var=value: 自定義變量
-f:調用awk腳本
program:pattern{action statements;..}
語句之間用分號分割
pattern和action:
pattern:部分決定動做語句什麼時候觸發及觸發事件 BEGIN,END (觸發條件)
action statements:對數據進行處理,放在{}內指明 print, printf (對數據處理動做)
program一般是被單引號或雙引號中
知識點整理
一、print
要點:
(1) 逗號分隔符
(2) 輸出的各item能夠字符串,也能夠是數值;當前記錄的字段、 變量或awk的表達式
(3) 如省略item,至關於print $0
示例:
[root@centos7 ~]# tail -3 /etc/fstab #源文件 UUID=0cd9ec5d-a77e-46f4-b218-19d914a5ed1e /app xfs defaults 0 0 UUID=3535b5f0-7b38-4cc9-a099-551fa388392c /boot xfs defaults 0 0 UUID=c424d9be-be2c-4e7c-a007-1af750d9310b swap swap defaults 0 0 [root@centos7 ~]# tail -3 /etc/fstab |awk '{print}' UUID=0cd9ec5d-a77e-46f4-b218-19d914a5ed1e /app xfs defaults 0 0 UUID=3535b5f0-7b38-4cc9-a099-551fa388392c /boot xfs defaults 0 0 UUID=c424d9be-be2c-4e7c-a007-1af750d9310b swap swap defaults 0 0 [root@centos7 ~]# tail -3 /etc/fstab |awk '{print "wang"}' wang wang wang [root@centos7 ~]# tail -3 /etc/fstab |awk '{print $0}' UUID=0cd9ec5d-a77e-46f4-b218-19d914a5ed1e /app xfs defaults 0 0 UUID=3535b5f0-7b38-4cc9-a099-551fa388392c /boot xfs defaults 0 0 UUID=c424d9be-be2c-4e7c-a007-1af750d9310b swap swap defaults 0 0 [root@centos7 ~]# tail -3 /etc/fstab |awk '{print $2$4}' /appdefaults /bootdefaults swapdefaults、 [root@centos7 ~]# tail -3 /etc/fstab |awk '{print $2,$4}' /app defaults /boot defaults swap defaults [root@centos7 ~]# tail -3 /etc/fstab |awk '{print $2"\t"$4}' /appdefaults /bootdefaults swapdefaults
二、變量
2.1 內建命令
FS:輸入字段分隔符,默認爲空白字符
~]# awk -v FS=: '{print $1,FS,$3}' /etc/passwd ~]# awk -F":" '{print $1,$3}' /etc/passwdOFS:輸出字段分隔符,默認爲空白字符
~]# awk -v FS=":" -v OFS=: '{print $1,$3,$7 }' /etc/passwdRS:輸入記錄分隔符,指定輸入時的換行符,原換行符仍有效
~]# awk -v RS=''^C{print}' /etc/passwdORS:輸出記錄分隔符,輸出時用指定符號代替換行符
~]#awk -v RS=' ' -v ORS=' ' ‘{print }’ /etc/passwdARGC:命令行參數的個數
~]# awk -F: ‘{print NF}’ /etc/fstab,引用內置變量不用$ ~]# awk -F: '{print $(NF-1)}' /etc/passwdARGV:數組,保存命令行給定的各參數
~]# [root@centos7 ~]# awk -F: '{print NF}' /etc/passwd 7 7 ~]# awk -F: '{print $(NF-1)}' /etc/passwd /root /bin
NF:字段數量
~]# ~]# awk '{print NR}' /etc/fstab ; awk END'{print NR}' /etc/fstab
NR:行號
~]# awk {print NR}' /etc/fstab /etc/fatabFNR:個文件分別計數,行號
~]#awk {print FNR}' /etc/fstab /etc/fatab
FILENAME:當前文件名
~]# awk '{print FILENAME}' /etc/fstab /etc/fstab /etc/fstab
ARGC:命令行參數的個數
~
]# awk '{print ARGC}' /etc/fstab /etc/inittab ~]# awk 'BEGIN{print ARGC}' /etc/fstab /etc/inittab
ARGV:數組,保存的是命令行所給定的各參數
~]# awk 'BEGIN{print ARGV[0]}' /etc/fstab /etc/inittab awk ~]# awk 'BEGIN{print ARGV[1]}' /etc/fstab /etc/inittab /etc/fstab ~]# awk 'BEGIN{print ARGV[2]}' /etc/fstab /etc/inittab /etc/inittab ~]# awk 'BEGIN{print ARGV[3]}' /etc/fstab /etc/inittab #沒有索引爲空
2.2 自定義變量
選項位置定義:-v var=hello
在program中定義:awk ‘BEGIN{test=」hello」;print test}’
示例:
[root@centos7 ~]# awk -v test='hello gawk' '{print test}' /etc/fstab hello gawk hello gawk hello gawk root@centos7 ~]# awk -v test='hello gawk' 'BEGIN{print test}' /etc/fstab hello gawk [root@centos7 ~]# awk 'BEGIN{r=test="hello,gawk";print test}' /etc/fstab hello,gawk [root@centos7 ~]# awk -F: '{sex="male";print $1,sex,age;age=18}' /etc/passwd root male bin male 18 daemon male 18 [root@centos7 ~]# cat awk.txt #腳本實現awk輸出 {print script,$1,$2} [root@centos7 ~]# awk -F: -f awk.txt txt="awk" /etc/passwd #-f調用swk腳本 root x bin x
三、 printf命令
格式化輸出:printf 「FORMAT」, item1, item2, ...
(1) 必須指定FORMAT
(2) 不會自動換行,須要顯式給出換行控制符,\n
(3) FORMAT中須要分別爲後面每一個item指定格式符
print不須要指定,printf須要指定format
printf後面的字串須要使用雙引號
字串定義後的內容須要使用」,」分隔,後面直接跟Item1,item2….
format用於指定後面的每一個item的輸出格式
printf語句不會自動打印換行符\n
格式符
%s: 顯示字符串
%d,%i: 顯示十進制整數
%e,%E: 科學計數法數值顯示
%f: 顯示爲浮點數
%g,%G: 以科學數法或浮點形式顯示數值
%c: 顯示字符的ASCII碼
%u: 無符號整數
%%: 顯示%號自身,至關於轉義
修飾符
N: 顯示寬度
-: 左對齊(默認爲右對齊)
+: 顯示數值符號
示例:
[root@centos7 ~]# awk -F: '{printf"%s",$1}' /etc/passwd rootbindaemonadmlpsyncshutdownhaltmailoperatorgamesftpnobodysystemd-networkdbuspolkitdabrtlibstoragemgmtrpccolordsaslauthrtkitchronyqemutssusbmuxdgeocluerpcusernfsnobodyradvdsetroubleshootpulsegdmgnome-initial-s [root@centos7 ~]# awk -F: '{printf"%s\n",$1}' /etc/passwd root bin daemon adm lp sync shutdown halt mail operator [root@centos7 ~]# awk -F: '{printf"%-20s %10d\n",$1,$3}' /etc/passwd root 0 bin 1 daemon 2 adm 3 lp 4 [root@centos7 ~]# awk -F: '{printf"%-20.2s %10d\n",$1,$3}' /etc/passwd ro 0 bi 1 da 2 [root@centos7 ~]# awk -F: '{print "username:%s\n",$1}' /etc/passwd username:%s root username:%s bin [root@centos7 ~]# awk -F: '{printf "username:%s,UID:%d\n",$1,$3}' /etc/passwd username:root,UID:0 username:bin,UID:1 username:daemon,UID:2 username:adm,UID:3 username:lp,UID:4 username:sync,UID:5 [root@centos7 ~]# awk -F: '{printf "username:%15s,UID:%d\n",$1,$3}' /etc/passwd username: root,UID:0 username: bin,UID:1 username: daemon,UID:2 #%15s 右對齊 username: adm,UID:3 [root@centos7 ~]# awk -F: '{printf "username:%-15s,UID:%d\n",$1,$3}' /etc/passwd username:root ,UID:0 username:bin ,UID:1 username:daemon ,UID:2 #%-15s 左對齊 username:adm ,UID:3 [root@centos7 ~]# awk -F: '{printf "username:%-20s salary:%-10.2f shell:%s\n",$1,$3,$7}' /etc/passwd username:root salary:0.00 shell:/bin/bash username:bin salary:1.00 shell:/sbin/nologin username:daemon salary:2.00 shell:/sbin/nologin username:adm salary:3.00 shell:/sbin/nologin username:lp salary:4.00 shell:/sbin/nologin username:sync salary:5.00 shell:/bin/sync username:shutdown salary:6.00 shell:/sbin/shutdown username:halt salary:7.00 shell:/sbin/halt
四、操做符
算數操做符
x+y, x-y, x*y, x/y, x^y, x%y
-x: 轉換爲負數 +x: 轉換爲數值
字符串操做符:沒有符號的操做符,字符串鏈接
賦值操做符
=, +=, -=, *=, /=, %=, ^=,++, —
比較操做符
==, !=, >, >=, <, <=
模式匹配符
~:左邊是否和右邊匹配包含!~:是否不匹配
示例: 計算1加到100和爲多少[root@centos7 ~]# echo {1..100}|tr " " + |bc 5050 [root@centos7 ~]# for ((sum=0,i=1;i<=100;i++));do let sum+=i;done;echo $sum 5050 [root@centos7 ~]# awk BEGIN'{for(i=1;i<=100;i++){sum+=i};print sum}' 5050 [root@centos7 ~]# awk BEGIN'{i=1;while (i<=100) {sum+=i;i++};print sum}' 5050 計算1加到100奇偶數和 #100之內偶奇數相加之和 [root@centos6 ~]# awk BEGIN'{sum=0;for(i=1;i<=100;i++){if(i%2==0){continue};sum+=i};print sum}' 2500 #100之內偶數相加之和 [root@centos6 ~]# awk BEGIN'{sum=0;for(i=1;i<=100;i++){if(i%2==1){continue};sum+=i};print sum}' 2550 #列出十之內的奇數 [root@centos6 ~]# seq 10 |awk '{if($1%2==0){next};print $1}' 1 3 5 7 9 #列出十之內的偶數 [root@centos6 ~]# seq 10 |awk '{if($1%2!=0){next};print $1}' 2 4 6 8 10 [root@centos7 ~]# awk -F: '$0 ~ /root/' /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin root@centos7 ~]# awk -F: '$0 ~ /root/{print $1}' /etc/passwd root operator [root@centos7 ~]# awk -F: '$0 ~ /^root/' /etc/passwd root:x:0:0:root:/root:/bin/bash [root@centos7 ~]# awk -F: '$0 !~ /root/' /etc/passwd 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 ....... [root@centos7 ~]# awk -F: '$3==0' /etc/passwd root:x:0:0:root:/root:/bin/bash
性能比較
[root@centos7 ~]# time(seq –s 」+」 1000000|bc) #bc運算 seq: invalid floating point argument: –s Try 'seq --help' for more information. real 0m0.004s user 0m0.000s sys 0m0.003s [root@centos7 ~]# time(for ((i=0;i<=1000000;i++));do let total+=i;done;echo $total) #shell for運算 500000500000 real 0m7.236s user 0m6.990s sys 0m0.231s [root@centos7 ~]# [root@centos7 ~]# time(total=0;for i in {1..1000000};do total=$(($total+i));done;echo $total) #bash for運算 500000500000 real 0m7.150s user 0m4.949s sys 0m0.878s [root@centos7 ~]# time (awk 'BEGIN{ total=0;for(i=0;i<=1000000;i++){total+=i;};print total;}') #awk運算 500000500000 real 0m0.217s user 0m0.092s sys 0m0.002s
邏輯操做符
與&&,或||,非! :
示例:
[root@centos7 ~]# awk -F: '$3>=0 && $3<=1000 {print $1}' /etc/passwd root bin daemon [root@centos7 ~]# awk -F: '$3==0 || $3<=1000 {print $1}' /etc/passwd root bin daemon [root@centos7 ~]# awk -F: '!($3==0) {print $1}' /etc/passwd bin daemon adm [root@centos7 ~]# awk -F: '($3>=1000) {print $3}' /etc/passwd 65534 1000 1001 1002 4444 [root@centos7 ~]# awk -F: '!($3>=1000) {print $1}' /etc/passwd root bin daemon adm [root@centos7 ~]# awk -F: '$3>=1000{print $1,$3}' /etc/passwd nfsnobody 65534 li 1000 123 1001 12 1002 19 4444
函數調用: function_name(argu1, argu2, ...)
條件表達式(三目表達式):
selector?if-true-expression:if-false-expression
示例:
[
[root@centos7 ~]# awk -F: '{$3>=1000?UserType="Common User":UserType="Sysasmin or sysUser";printf "%15s: %s\n",$1,UserType}' /etc/passwd root: Sysasmin or sysUser bin: Sysasmin or sysUser daemon: Sysasmin or sysUser adm: Sysasmin or sysUser lp: Sysasmin or sysUser sync: Sysasmin or sysUser shutdown: Sysasmin or sysUser halt: Sysasmin or sysUser mail: Sysasmin or sysUser operator: Sysasmin or sysUser games: Sysasmin or sysUser ftp: Sysasmin or sysUser nobody: Sysasmin or sysUser systemd-network: Sysasmin or sysUser dbus: Sysasmin or sysUser polkitd: Sysasmin or sysUser abrt: Sysasmin or sysUser libstoragemgmt: Sysasmin or sysUser rpc: Sysasmin or sysUser colord: Sysasmin or sysUser saslauth: Sysasmin or sysUser rtkit: Sysasmin or sysUser chrony: Sysasmin or sysUser qemu: Sysasmin or sysUser tss: Sysasmin or sysUser usbmuxd: Sysasmin or sysUser geoclue: Sysasmin or sysUser rpcuser: Sysasmin or sysUser nfsnobody: Common User radvd: Sysasmin or sysUser setroubleshoot: Sysasmin or sysUser pulse: Sysasmin or sysUser gdm: Sysasmin or sysUser gnome-initial-setup: Sysasmin or sysUser sshd: Sysasmin or sysUser avahi: Sysasmin or sysUser postfix: Sysasmin or sysUser ntp: Sysasmin or sysUser tcpdump: Sysasmin or sysUser li: Common User apache: Sysasmin or sysUser 123: Common User 12: Common User 19: Common User
五、PATTERN
PATTERN:根據pattern條件,過濾匹配的行,再作處理
(1)若是未指定:空模式,匹配每一行
(2) /regular expression/:僅處理可以模式匹配到的行,須要用/ /括起來
awk '/^UUID/{print $1}' /etc/fstab 僅處理匹配到的行
awk '!/^UUID/{print $1}' /etc/fstab 僅處理匹配到的行
(3) relational expression: 關係表達式,結果有「真」有「假」;結果爲「真」纔會被處理 ;
真:結果爲非0值,非空字符串
假:結果爲空字符串或0值
(4) line ranges:行範圍
startline,endline:/pat1/,/pat2/ 處理 pattern1 到 pattern2 之間
注意:不支持直接給出數字格式
(5) BEGIN/END模式
BEGIN{}: 僅在開始處理文件中的文本以前執行一次
END{}:僅在文本處理完成以後執行一次
示例:
[root@centos7 ~]# df #處理前顯示 Filesystem 1K-blocks Used Available Use% Mounted on /dev/sda2 20961280 3750180 17211100 18% / devtmpfs 485144 0 485144 0% /dev tmpfs 499848 0 499848 0% /dev/shm tmpfs 499848 19832 480016 4% /run tmpfs 499848 0 499848 0% /sys/fs/cgroup /dev/sda5 20961280 32948 20928332 1% /app /dev/sda1 201380 138984 62396 70% /boot tmpfs 99972 36 99936 1% /run/user/0 /dev/sr0 8490330 8490330 0 100% /media [root@centos7 ~]# df |grep /dev/sd |awk '{printf "DevName:%s Used:%s\n",$1,$5}' #顯示/dev/sd開頭的行並對其輸出顯示進行優化 DevName:/dev/sda2 Used:18% DevName:/dev/sda5 Used:1% DevName:/dev/sda1 Used:70% [root@centos7 ~]# df | awk '$0 ~ "/dev/sd" {printf "DevName:%-10s Used:%s\n",$1,$5}' DevName:/dev/sda2 Used:18% DevName:/dev/sda5 Used:1% DevName:/dev/sda1 Used:70% [root@centos7 ~]# df |awk '$1~"^/dev/sd[[:lower:]][[:digit:]]\\>" && $5>=10 {printf "Filesystem: %-15s Used: %s\n",$1,$5}' Filesystem: /dev/sda2 Used: 18% Filesystem: /dev/sda1 Used: 70% [root@centos7 ~]# df |awk '/\/dev\/sd[[:lower:]][[:digit:]]\>/{if($5>10){printf "DevName:%-10s Used:%s\n",$1,$5}}' DevName:/dev/sda2 Used:18% DevName:/dev/sda1 Used:70% [root@centos7 ~]# awk -F: '$3<1000{print $1,$3 }' /etc/passwd root 0 bin 1 daemon 2 adm 3 lp 4 sync 5 shutdown 6 halt 7 mail 8 operator 11 games 12 ftp 14 nobody 99 systemd-network 192 dbus 81 polkitd 999 abrt 173 libstoragemgmt 998 rpc 32 colord 997 saslauth 996 rtkit 172 chrony 995 qemu 107 tss 59 usbmuxd 113 geoclue 994 rpcuser 29 radvd 75 setroubleshoot 993 pulse 171 gdm 42 gnome-initial-setup 992 sshd 74 avahi 70 postfix 89 ntp 38 tcpdump 72 apache 48 [root@centos7 ~]# awk -F: '$NF=="/bin/bash"{print $1,NF }' /etc/passwd #匹配最後一列爲"/bin/bash",輸出$1和列數NF的值 root 7 li 7 123 7 12 7 19 7 [root@centos7 ~]# awk -F: '$NF=="/bin/bash"{print $1,$NF }' /etc/passwd #匹配最後一列爲"/bin/bash",輸出$1和$NF變量的值 root /bin/bash li /bin/bash 123 /bin/bash 12 /bin/bash 19 /bin/bash [root@centos7 ~]# awk -F: '$NF ~ "/bin/bash"{print $1,$NF }' /etc/passwd # root /bin/bash li /bin/bash 123 /bin/bash 12 /bin/bash 19 /bin/bash [root@centos7 ~]# awk -F: '$NF ~ /bash$/{print $1,$NF }' /etc/passwd root /bin/bash li /bin/bash 123 /bin/bash 12 /bin/bash 19 /bin/bashm [root@centos7 ~]# awk -F: '(NR<=28&&NR>=10){print $1}' /etc/passwd operator games ftp nobody systemd-network dbus polkitd abrt libstoragemgmt rpc colord saslauth rtkit chrony qemu tss usbmuxd geoclue rpcuser [root@centos7 ~]# awk '/UUID/{print $1}' /etc/fstab UUID=24d11781-1f0f-4fe5-805c-6ca807fd24ff UUID=0cd9ec5d-a77e-46f4-b218-19d914a5ed1e UUID=3535b5f0-7b38-4cc9-a099-551fa388392c UUID=c424d9be-be2c-4e7c-a007-1af750d9310b [root@centos7 ~]# awk -F: '/^root\>/,/^ftp\>/{print $1}' /etc/passwd #root開頭到ftp開頭之間的行 root bin daemon adm lp sync shutdown halt mail operator games ftp [root@centos7 ~]# awk -F: 'BEGIN{print " USER USERID"}/^root\>/,/^ftp\>/{printf "%20s %s %-5s\n", $1,":",$3}END{print " end file"}' /etc/passwd #BEGIN指定(修飾)第一個輸出,/^root\>/,/^ftp\>指定(修飾)範圍第二個輸出,END指定(修飾)最後一個輸出範圍 USER USERID root : 0 bin : 1 daemon : 2 adm : 3 lp : 4 sync : 5 shutdown : 6 halt : 7 mail : 8 operator : 11 games : 12 ftp : 14 end file [root@centos7 ~]# awk -F: 'BEGIN{print "user uid \n------------------"}/^root\>/,/^ftp\>/{print $1,$3}' /etc/passwd user uid ------------------ root 0 bin 1 daemon 2 adm 3 lp 4 sync 5 shutdown 6 halt 7 mail 8 operator 11 games 12 ftp 14 [root@centos7 ~]# awk -F: 'BEGIN{print "user uid \n------------------"}/^root\>/,/^ftp\>/{print $1,$3}END{print "==============="}' /etc/passwd user uid ------------------ root 0 bin 1 daemon 2 adm 3 lp 4 sync 5 shutdown 6 halt 7 mail 8 operator 11 games 12 ftp 14 ===============
六、經常使用的action
(1) Expressions:算術,比較表達式等
(2) Control statements:if, while等
(3) Compound statements:組合語句
(4) input statements
(5) output statements:print等
7控制語句
簡述控制語句格式:
if(condition){statments}
if(condition){statments} else {statments}
while(condition){statments}
do {statements} while (condition)
for(expr1;expr2;expr3){statements}
break
continue
delete array [index]
delete array
exit
{statements}
7.1 if-else
語法:
if(condition){statments}
if(condition){statments} else {statments}
if(condition1){statement1}else if(condition2){statement2} else{statement3}
使用場景:對awk取得的整行或某個字段作條件判斷
示例:
[root@centos7 ~]# awk 'BEGIN{ test=100;if(test>90){print "very good"}else if(test>60){ print "good"}else{print "no pass"}}' very good 成績爲100;大於90打印「very good」;大於60打印「good」;其他打印「no pass」 [root@centos7 ~]# awk '{if($3>=1000){printf "Common user: %s\n",$1 } else{printf "root or sysuser : %s\n",$1}}' /etc/passwd root or sysuser : root:x:0:0:root:/root:/bin/bash root or sysuser : bin:x:1:1:bin:/bin:/sbin/nologin root or sysuser : daemon:x:2:2:daemon:/sbin:/sbin/nologin root or sysuser : adm:x:3:4:adm:/var/adm:/sbin/nologin root or sysuser : lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin root or sysuser : sync:x:5:0:sync:/sbin:/bin/sync root or sysuser : shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown root or sysuser : halt:x:7:0:halt:/sbin:/sbin/halt root or sysuser : mail:x:8:12:mail:/var/spool/mail:/sbin/nologin root or sysuser : operator:x:11:0:operator:/root:/sbin/nologin root or sysuser : games:x:12:100:games:/usr/games:/sbin/nologin [root@centos7 ~]# awk -F: '{if($NF=="/bin/bash")print $1}' /etc/passwd #NF字段數量,$NF表示最後字段的值,判斷字段值等於/bin/bash root li 123 12 19 [root@centos7 ~]# awk '{if(NF>5)print $0}' /etc/passwd #NF字段數量,判斷字段數大於5的行 tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin [root@centos7 ~]# awk '{if(NF>5)print $0}' /etc/fstab # Created by anaconda on Tue Jan 9 05:14:54 2018 # Accessible filesystems, by reference, are maintained under '/dev/disk' # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info UUID=24d11781-1f0f-4fe5-805c-6ca807fd24ff / xfs defaults 0 0 UUID=0cd9ec5d-a77e-46f4-b218-19d914a5ed1e /app xfs defaults 0 0 UUID=3535b5f0-7b38-4cc9-a099-551fa388392c /boot xfs defaults 0 0 UUID=c424d9be-be2c-4e7c-a007-1af750d9310b swap swap defaults 0 0 [root@centos7 ~]# df -h |awk -F% '{print $1}' Filesystem Size Used Avail Use /dev/sda2 20G 3.6G 17G 18 devtmpfs 474M 0 474M 0 tmpfs 489M 0 489M 0 tmpfs 489M 20M 469M 4 tmpfs 489M 0 489M 0 /dev/sda5 20G 33M 20G 1 /dev/sda1 197M 136M 61M 70 tmpfs 98M 36K 98M 1 /dev/sr0 8.1G 8.1G 0 100 [root@centos7 ~]# df -h |awk -F% '{print $1}'|awk '{print $NF}' Use 18 0 0 4 0 1 70 1 100 [root@centos7 ~]# df -h |awk -F% '/^\/dev/{print $1}'|awk '{print $NF}' 18 1 70 100 #將/etc/passwd第一列看成姓名,第三列看成工資,打印報表,要求顯示: #Name:zhangsan Salary:3300 Level:High #工資大於3000的,Level顯示High,大於1000,小於等於3000的顯示Soso,小於1000的顯示LOW。 [root@centos7 ~]# awk -F: '{if($3>3000){Level="High"}else if($3>1000 && $3<=3000){Level="Soso"}else{Level="Low"};printf "Name:%-20s Salary:%-20d Level:%s\n",$1,$3,Level}' /etc/passwd Name:root Salary:0 Level:Low Name:bin Salary:1 Level:Low Name:daemon Salary:2 Level:Low Name:adm Salary:3 Level:Low Name:lp Salary:4 Level:Low Name:sync Salary:5 Level:Low Name:shutdown Salary:6 Level:Low Name:halt Salary:7 Level:Low Name:mail Salary:8 Level:Low Name:operator Salary:11 Level:Low Name:games Salary:12 Level:Low Name:ftp Salary:14 Level:Low Name:nobody Salary:99 Level:Low Name:systemd-network Salary:192 Level:Low Name:dbus Salary:81 Level:Low Name:polkitd Salary:999 Level:Low Name:abrt Salary:173 Level:Low Name:libstoragemgmt Salary:998 Level:Low Name:rpc Salary:32 Level:Low Name:colord Salary:997 Level:Low Name:saslauth Salary:996 Level:Low Name:rtkit Salary:172 Level:Low Name:chrony Salary:995 Level:Low Name:qemu Salary:107 Level:Low Name:tss Salary:59 Level:Low Name:usbmuxd Salary:113 Level:Low Name:geoclue Salary:994 Level:Low Name:rpcuser Salary:29 Level:Low Name:nfsnobody Salary:65534 Level:High Name:radvd Salary:75 Level:Low Name:setroubleshoot Salary:993 Level:Low Name:pulse Salary:171 Level:Low Name:gdm Salary:42 Level:Low Name:gnome-initial-setup Salary:992 Level:Low Name:sshd Salary:74 Level:Low Name:avahi Salary:70 Level:Low Name:postfix Salary:89 Level:Low Name:ntp Salary:38 Level:Low Name:tcpdump Salary:72 Level:Low Name:li Salary:1000 Level:Low Name:apache Salary:48 Level:Low Name:123 Salary:1001 Level:Soso Name:12 Salary:1002 Level:Soso Name:19 Salary:4444 Level:High
7.2 while循環
語法:while(condition){statments}
意義:條件」真」,進入循環;條件」假」,退出循環
使用場景:對於行內的多個字段逐一相似處理時使用,對數組中的個元素逐一處理時使用。
[root@centos7 ~]# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF){print $1,length($i);i++}}' /etc/grub2.cfg linux16 7 linux16 30 linux16 46 linux16 2 linux16 4 linux16 5 linux16 16 linux16 7 linux16 50 linux16 46 linux16 2 linux16 4 linux16 5 [root@centos7 ~]# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF){if(length($i)>=40){print $1,length($i)};i++}}' /etc/grub2.cfg #以空白符開頭後跟」linux16″的行中,把字符數大於40的字符串打印出來。 linux16 46 linux16 50 linux16 46
7.3 do-while循環
語法:do {statements} while (condition)
(不管真假,至少執行一次循環體 )
示例:
[root@centos7 ~]# seq 3|awk 'BEGIN{i=1;print i++,i}' #i的值:先輸出i的值,在作(加法)運算 1 2 [root@centos7 ~]# seq 3|awk 'BEGIN{i=1;print ++i,i}' #i的值:先作(加法)運算,在輸出i 的值 2 2
[root@centos7 ~]# awk 'BEGIN{ total=0;i=0;do{ total+=i;i++;}while(i<=100);print total}' #累加運算:計算0-100之和 5050
7.4 for循環
語法:for(expr1;expr2;expr3) {statement;…}
常見用法:for(variable assignment;condition;iteration process) {for-body}
特殊用法:
可以遍歷數組中的元素
語法:for(var in array) {for-body}
示例:
[root@centos7 ~]# awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print$i,length($i)}}' /etc/grub2.cfg #遍歷:統計以linux16開頭的行各字符串出現次數 linux16 7 /vmlinuz-3.10.0-693.el7.x86_64 30 root=UUID=24d11781-1f0f-4fe5-805c-6ca807fd24ff 46 ro 2 rhgb 4 quiet 5 LANG=en_US.UTF-8 16 linux16 7 /vmlinuz-0-rescue-ff4aa58d9e1f44f7b7aae5f6fd1a3242 50 root=UUID=24d11781-1f0f-4fe5-805c-6ca807fd24ff 46 ro 2 rhgb 4 quiet 5
7.5 switch語句
語法:switch(expression) {case VALUE1 or /REGEXP/: statement1; case VALUE2 or /REGEXP2/: statement2; ...; default: statementn}
7.6 break和continue
break [n]
continue [n]
awk ‘BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==0)continue;sum+=i}print sum}’
awk ‘BEGIN{sum=0;for(i=1;i<=100;i++){if(i==66)break;sum+=i}print sum}’
7.7 net
提早結束對本行處理而直接進入下一行處理(awk自身循環)
示例:
[root@centos7 ~]# awk -F: '{if($3%2!=0) print $1,$3}' /etc/passwd root 0 daemon 2 lp 4 shutdown 6 mail 8 games 12 ftp 14 systemd-network 192 libstoragemgmt 998 rpc 32 saslauth 996 rtkit 172 geoclue 994 nfsnobody 65534 gdm 42 gnome-initial-setup 992 sshd 74 avahi 70 ntp 38 tcpdump 72 li 1000 apache 48 12 1002
[root@centos7 ~]# seq 20 | awk -F: '{if($1%2==0)next ; print $1}' #打印奇數行;匹配$1%2取餘數的等於0的結束循環 1 3 5 7 9 11 13 15 17 19
八、array(數組 )
關聯數組:array[index-expression]
index-expression:
(1) 可以使用任意字符串;字符串要使用雙引號括起來
(2) 若是某數組元素事先不存在,在引用時,awk會自動建立 此元素,並將其值初始化爲「空串」
若要判斷數組中是否存在某元素,要使用「index in array」格 式進行遍歷
若要遍歷數組中的每一個元素,要使用for循環;
for(var in array) {for-body}
注意:var會遍歷array的每一個索引;
state["LISTEN"]++
state["ESTABLISHED"]++
九、函數
數值處理:
rand():返回0和1之間一個隨機數
[root@centos7 ~]# awk 'BEGIN{srand();print int(rand()*100)}' #隨機一個兩位數的整數,*100 71
字符串處理:
length([s]):返回指定字符串的長度
sub(r,s,[t]):對t字符串進行搜索r表示的模式匹配的內容,並將第一個匹 配的內容替換爲s
[root@nanyibo ~]# echo "2018:3:30 17:38:30" |awk 'sub(/:/,"-",$1)' 2018-3:30 17:38:30
gsub(r,s,[t]):對t字符串進行搜索r表示的模式匹配的內容,並所有替換 爲s所表示的內容
[root@nanyibo ~]# echo "2018:3:30 17:38:30" |awk 'gsub(/:/,"-",$1)'
2018-3-30 17:38:30
split(s,array,[r]):以r爲分隔符,切割字符串s,並將切割後的結果保存 至array所表示的數組中,第一個索引值爲1,第二個索引值爲2,…
netstat -tan | awk '/^tcp\>/{split($5,ip,":");count[ip[1]]++} END{for (i in count) {print i,count[i]}}' #先進行分割,取出第五列對第五列作分割取出以分隔符:的第一列,設置變量count索引爲ip[1]作加法運算,只輸出一次結果。
自定義函數
格式:
function name ( parameter, parameter, ... ) { statements return expression }
示例:
#cat fun.awk function max( v1,v2) { v1>v2?var=v1:var=v2 return var } BEGIN{a=3;b=2;print max(a,b)} #awk –f fun.awk
示例:
[root@nana ~]# cat fi.txt 1 2 3 4 5 6 7 8 9 10 11 12 12 14 15 16 17 18 19 20 [root@nana ~]# awk '{i=1;sum=0;while(i<=NF){sum+=$i;i++};print sum}' f1.txt 顯示每行各自的總行 55 155 [root@nana ~]# awk '{i=1;while(i<=NF){sum+=$i;i++};print sum}' f1.txt 每行顯示一次總和 55 210 [root@nana ~]# awk '{i=1;while(i<=NF){sum+=$i;i++}}END{print sum}' f1.txt 只顯示總和 210
對十之內整數奇數輸出jishu,偶數輸出偶數
效果以下:
1 jishu
2 oushu
3 jishu
[root@centos7 /]# echo {1..10} |awk '{i=1;while(i<=NF){if($i%2==0){print $i,"is oushu"} else{print $i, "is jishu"};i++}}' 1 is jishu 2 is oushu 3 is jishu 4 is oushu 5 is jishu 6 is oushu 7 is jishu 8 is oushu 9 is jishu 10 is oushu
[root@centos7 ~]# awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays) {print weekdays[i]}}' Tuesday Monday [root@centos7 ~]# awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays) {print weekdays[i] ,i}}' #i的值爲每次數組weekdays的索引,這個過程稱爲遍歷 Tuesday tue Monday mon
函數統計類型出現次數
~]# netstat -tan |awk '/^tcp\>/{state[$NF]++}END{for (i in state){ print i,state[i]}}' #函數state中下標爲$NF的值:LISTEN和ESTABLISHED,他們的值作++運算, #END{}:僅在文本完成以後執行一次,後邊for循環只作一次, #i變量的值爲:數組state的下標,也就是:LISTEN和ESTABLISHED。 #print i的值爲for訓話i的值,就是$NF的值:LISTEN和ESTABLISHED。 #state[i]的值爲,END前邊完成時的值++的相加之和, #也就是state數組的值:state[LISTEN]=3和state[ESTABLISHED]=1 LISTEN 8 ESTABLISHED 3
顯示/bash類型次數
[root@centos7 ~]# awk -F: '{shell[$7]++}END{for(n in shell){print n,shell[n]}}' /etc/passwd /bin/sync 1 /bin/bash 5 /sbin/nologin 36 /sbin/halt 1 /sbin/shutdown 1
統計http日誌文件,IP地址訪問次數
[root@centos7 ~]# awk '{ip[$1]++}END{for(i in ip){print i ,ip[i]}}' /var/log/httpd/access_log 172.18.253.55 1788 172.18.251.122 52 172.18.251.150 34 172.18.251.141 30 172.18.251.160 157 172.18.251.170 457 172.18.251.107 14 172.18.251.109 51 172.18.251.145 50 172.18.0.223 12 172.18.253.21 74087 ::1 15 172.18.251.147 354 172.18.254.78 183 172.18.251.157 330 172.18.252.134 514 172.18.251.149 158 172.18.254.6 1643 172.18.250.183 81 172.18.251.21 81 172.18.254.34 659
awk實現取出從定向
[root@centos7 ~]# awk -F: '! shell[$7]++' /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt
去重
[root@centos6 ~]#awk -F: '!shell[$0]++' /etc/passwd #去重
統計/etc/fstab文件中每一個文件系統類型出現的次數;
#源文件 [root@centos7 ~]# awk '/^UUID/{print $0}' /etc/fstab UUID=24d11781-1f0f-4fe5-805c-6ca807fd24ff / xfs defaults 0 0 UUID=0cd9ec5d-a77e-46f4-b218-19d914a5ed1e /app xfs defaults 0 0 UUID=3535b5f0-7b38-4cc9-a099-551fa388392c /boot xfs defaults 0 0 UUID=c424d9be-be2c-4e7c-a007-1af750d9310b swap swap defaults 0 0 [root@centos7 ~]# awk '/^UUID/{fs[$3]++}END{for(i in fs) {print i,fs[i]}}' /etc/fstab swap 1 xfs 3
統計指定文件中每一個單詞出現的次數;
[root@centos7 ~]# awk '{for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count) {print i,count[i]}}' /etc/fstab UUID=c424d9be-be2c-4e7c-a007-1af750d9310b 1 Tue 1 man 1 and/or 1 UUID=0cd9ec5d-a77e-46f4-b218-19d914a5ed1e 1 maintained 1 xfs 3 Accessible 1 # 7 are 1 defaults 4 Jan 1 blkid(8) 1 / 1 0 8 See 1 Created 1 05:14:54 1 on 1 mount(8) 1 9 1 anaconda 1 UUID=3535b5f0-7b38-4cc9-a099-551fa388392c 1 fstab(5), 1 /app 1 /boot 1 findfs(8), 1 2018 1 '/dev/disk' 1 by 2 /etc/fstab 1 pages 1 more 1 info 1 swap 2 filesystems, 1 reference, 1 UUID=24d11781-1f0f-4fe5-805c-6ca807fd24ff 1 for 1 under 1
腳本實現AWK
system命令
空格是awk中的字符串鏈接符,若是system中須要使用awk中 的變量可使用空格分隔,或者說除了awk的變量外其餘一概 用""引用起來。
awk BEGIN'{system("hostname") }' awk 'BEGIN{score=100; system("echo your score is " score) }'
[root@nanyibo ~]# cat awk.txt function max(v1,v2){ v1>v2?var=v1:var=v2 return var } BEGIN{print max(a,b)} [root@nanyibo ~]# awk -v a=30 -v b=20 -f awk.txt 30 [root@nanyibo ~]# awk -v a=10 -v b=20 -f awk.txt 20
將awk程序寫成腳本,直接調用或執行
示例:
#cat f1.awk {if($3>=1000)print $1,$3} #awk -F: -f f1.awk /etc/passwd #cat f2.awk #!/bin/awk –f #this is a awk script {if($3>=1000)print $1,$3} #chmod +x f2.awk #f2.awk –F: /etc/passwd
向awk腳本傳遞參
格式:
awkfile var=value var2=value2... Inputfile
注意:在BEGIN過程當中不可用。直到首行輸入完成之後,變 量纔可用。能夠經過-v 參數,讓awk在執行BEGIN以前獲得 變量的值。命令行中每個指定的變量都須要一個-v參數
示例:
#cat test.awk #!/bin/awk –f {if($3 >=min && $3<=max)print $1,$3} #chmod +x test.awk #test.awk -F: min=100 max=200 /etc/passwd