awk是文本三劍客之一,其實awk是一種語言,該語言的創始者定義爲」生成報表和格式化文本輸出「awk有不少種版本,這裏介紹的是GUN awk(gawk)linux
第一步:執行BEGIN{action}語句塊中的語句,該語句塊不依賴於文件,awk在執行是,將在讀取文件以前執行該語句中的語句塊,經常使用語變量的初始化,打印輸出表格的表頭。
第二步:從文件、標準輸入、上一條命令輸出結果輸入地區一行,而後進行pattern{aciton}語句塊,它將逐行掃描文件,從第一行到最後一行。若沒有提供pattern語句,則默認執行打印{print},即打印每個讀取到的行。
第三步:當讀至文件最後時,執行END{action}語句塊。一般用於彙總在pattern語句中執行的過程正則表達式
選項
-F"指定分隔符"
-v 自定義變量:定義變量
awk {print} file
awk將把file文件中的每一行都讀取一遍,而後輸出在終端上
輸入內置變量在文本中表明以下圖所示
apache
[root@centos6 ~]#awk -F: -v OFS="===" -v ORS="####" '{print $1,$2}' /etc/passwd #將輸出間隔符換爲===將換行符換爲###輸出結果以下 root===x####bin===x####daemon===x####adm===x####lp===x####sync===x####shutdown===x####halt===x####mail===x####uucp===x####operator===x####games===x####gopher===x####ftp===x####nobody===x####vcsa===x####saslauth===x####postfix===x####sshd===x####lin===x####tcpdump===x####hacker===x####dbus===x####test===x####apache===x####[root@centos6 ~]#
實例一centos
[root@centos6 ~]#awk -F: '{print $1,$3}' /etc/passwd #表示已「 : 」爲分隔符,取第一列和第三列,而後將結果輸出出來 root 0 bin 1 daemon 2 adm 3 lp 4 sync 5 shutdown 6 halt 7 mail 8 uucp 10 operator 11
awk命令的print打印內容也能夠不與文件有關,若沒有關係,則表示文件有多少行內容,就會打印本身所指定的內容,而在awk中,處理動做中的字母若不用" "引上則表示使用變量,因此若須要輸出字符串則須要用「 」引上。數字則不須要。
實例1、輸入分隔符數組
[root@centos6 ~]#echo {1..10} 1 2 3 4 5 6 7 8 9 10 [root@centos6 ~]#echo {1..10}|awk -v FS=" " '{print $1,$3}' 1 3
這裏表示本來輸出結果爲1到時,拿FS內置變量舉例,設置空白字符爲分隔符(默認分隔符就是空白字符,因此不指定結果也是同樣的,這裏只是爲了舉例說明),取1,3列,
實例2、替換輸出分隔符bash
[root@centos6 ~]#echo {1..10} | awk -v OFS=":" '{print $1,$2,$3}' 1:2:3
這裏OFS內置變量表示將輸出結果分隔符變成:,取1,2,3列
實例3、分別顯示兩個文本的行號app
[root@centos6 ~]#awk '{print FNR,$0}' /etc/fstab /etc/issue #表示分別顯示每個文件的行號 1 2 # 3 # /etc/fstab 4 # Created by anaconda on Fri Mar 9 08:50:54 2018 5 # 6 # Accessible filesystems, by reference, are maintained under '/dev/disk' 7 # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info 8 # 9 /dev/mapper/vgentos6-LogVol03 / ext4 defaults 1 1 10 /dev/mapper/vgentos6-LogVol02 /app ext4 defaults 1 2 11 UUID=8f86cc7e-f593-467d-b823-eae6610616a1 /boot ext4 defaults 1 2 12 /dev/mapper/vgentos6-LogVol00 /var ext4 defaults 1 2 13 /dev/mapper/vgentos6-LogVol01 swap swap defaults 0 0 14 tmpfs /dev/shm tmpfs defaults 0 0 15 devpts /dev/pts devpts gid=5,mode=620 0 0 16 sysfs /sys sysfs defaults 0 0 17 proc /proc proc defaults 0 0 18 /dev/cdrom /mnt/base auto defaults 0 0 1 CentOS release 6.9 (Final) 2 Kernel \r on an \m 3
在輸出內容時,print輸出只能輸出規定格式的內容,不能自定義格式,因此想要讓輸出結果根據本身所須要的格式輸出就須要用printf來定製格式
printf使用格式
awk ‘{printf "格式1 格式 ",$1,$2}’,格式必須和須要輸出的列一一對應
實例1、格式化輸出,讓文本左對齊ssh
[root@centos6 ~]#awk -F: '{printf "%-20s %-20d\n",$1,$3}' /etc/passwd root 0 bin 1 daemon 2 adm 3 lp 4 sync 5 shutdown 6 halt 7 mail 8 uucp 10
由於printf不會自動換行,因此在規定好的格式後面增長\n來起到換行符的做用,其中-表明左對齊,若須要右對齊則直接填整數便可tcp
awk也能夠進行數字間的運算,不但支持整數,並且支持小數
實例1、兩個數之間的運算ide
[root@centos6 ~]#awk 'BEGIN{print 5+10}' 15 [root@centos6 ~]#awk 'BEGIN{print 5.5+10.5}' 16 [root@centos6 ~]#awk 'BEGIN{print 40/3}' 13.3333
在賦值操做符中,sum+=i,就至關於sum=sum+i,
實例1、將100之內的數相加
seq 100 | awk '{sum+=$1}END{print sum}'
5050
由於awk原本就是針對行行的循環,能夠根據這個特性將1到100相加在END部分將sum值輸出,就實現了100百之內數相加
實例2、變量的自增
[root@centos6 ~]#awk '{print i++}' /etc/passwd 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
在awk中,變量一旦與運算符號結合使用,將認爲該變量的初始值爲0,這個這條語句表示從零開始/etc/passwd文件有多少行,i變量將自增幾回
awk模式通配符~,表示左邊的內容是否和右邊內容匹配包含,!~則表示不匹配
實例1、在文件中查找包含某字符的行
[root@centos6 ~]#awk -F: '$0 ~ /root/{print $0}' /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin
查看passwd這個文件包含root的行,並將其打印到終端
實例2、查找passwd文件中全部/bin/bash的行
[root@centos6 ~]#awk -F: '$0 ~ "/bin/bash"' /etc/passwd root:x:0:0:root:/root:/bin/bash lin:x:500:500::/home/lin:/bin/bash hacker:x:501:501::/home/hacker:/bin/bash test:x:502:502::/home/test:/bin/bash
因所搜內容中也包含 」 / 「 因此須要將搜索內容用雙引號引發來
&&:表示同時知足兩個條件
||:表示知足兩個條件中的一個便可
!:表示取匹配結果的反值
實例1、取同時知足兩個條件的結果&&
[root@centos6 ~]#awk -F: '$3>=50 && $3<=100{print $1,$3}' /etc/passwd nobody 99 vcsa 69 postfix 89 sshd 74 tcpdump 72 dbus 81
實例2、去知足一個或兩個條件的結果 ||
[root@centos6 ~]#awk -F: '$3>=50 || $3<=100{print $1,$3}' /etc/passwd root 0 bin 1 daemon 2 adm 3 lp 4 sync 5 shutdown 6 halt 7 mail 8 uucp 10 operator 11 games 12 gopher 13 ftp 14 nobody 99 vcsa 69 saslauth 499 postfix 89 sshd 74 lin 500 tcpdump 72 hacker 501 dbus 81 test 502 apache 48
經常使用於只有兩種狀況下的判斷,若是狀況過多,將不適合使用三目表達式來選擇
語法:判斷條件?條件爲真時執行語句:條件爲假時執行語句
實例1、將系統中全部用戶根據UID統計是系統用戶仍是普通用戶
[root@centos6 ~]#awk -F: '{$3>=500?usertype="common user":usertype="system user";print usertype,$1}' /etc/passwd #根據UID判斷當前系統中全部用戶是系統用戶仍是普通用戶 system user root system user bin system user daemon system user adm system user lp system user sync system user shutdown system user halt system user mail system user uucp system user operator system user games system user gopher system user ftp system user nobody system user vcsa system user saslauth system user postfix system user sshd common user lin system user tcpdump common user hacker system user dbus common user test system user apache
該模式下也支持擴展正則表達式,支持模糊搜索
1.若是未指定,空模式,匹配每一行,默認搜索每一行
實例一
[root@centos6 ~]#awk '{print $0}' /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
2./指定匹配字符/:僅處理可以模式匹配到的行須要用 / / 括起來,若匹配的行關鍵字中也有/則須要使用\/來轉譯
實例1、只有知足root爲行首的行纔會被匹配
[root@centos6 ~]#awk '/^root/{print $0}' /etc/passwd #表示只匹配root爲行首的行。 root:x:0:0:root:/root:/bin/bash
實例2、只要知足r..o條件的將所有匹配
[root@centos6 ~]#awk '/r..t/{print $0}' /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
3.關係表達式,若果爲真纔會被處理,
真:結果爲非0值或非空值
假:結果爲空字符串或0值
實例1、若條件爲0或者空值時,則不會輸出任何結果
[root@centos6 ~]#awk '0{print}' /etc/passwd
實例2、若條件爲非0或控制時,則打印結果
[root@centos6 ~]#awk '1{print}' /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
實例3、該表達式中,由於awk自帶行間的循環,又由於非空爲1,當第一次非空則將賦值1給i則有結果輸出,第二次則將一個非1則爲0,將0賦給i則第二個不輸出,依次類推則輸出結果以下
[root@centos6 ~]#seq 10 | awk 'i=!i' 1 3 5 7 9
4.行範圍,awk也能取匹配字符的行範圍 /匹配字符1/,/匹配字符2/處理動做
[root@centos6 ~]# awk '/^h/,/^f/' /etc/passwd halt:x:7:0:halt:/sbin:/sbin/halt mail:x:8:12:mail:/var/spool/mail:/sbin/nologin uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin operator:x:11:0:operator:/root:/sbin/nologin games:x:12:100:games:/usr/games:/sbin/nologin gopher:x:13:30:gopher:/var/gopher:/sbin/nologin ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin hacker:x:501:501::/home/hacker:/bin/bash dbus:x:81:81:System message bus:/:/sbin/nologin test:x:502:502::/home/test:/bin/bash apache:x:48:48:Apache:/var/www:/sbin/nologin
當遇到以h爲行首的行,則打印,到行首爲f結束,由於打印完以後有碰到h爲行首,則繼續打印,由於後面沒有h爲行首,則一直打印到就結束
5.BEGIN/END模式
BEGIN{}:僅在開始處理文本以前執行一次
BEGIN屬於在文本執行前執行的語句塊,它不依賴於任何文件或輸出結果
[root@centos6 ~]#awk 'BEGIN{print "test"}' test
END{}:僅在文本處理完成以後執行一次
END工做在awk處理完文本以後執行一次。能夠用於打印pattern語句塊執行過程的結果
它也依賴於文件或輸出結果
[root@centos6 ~]#awk 'END{print "test"}' /etc/passwd test
1.if else
語法
if(判斷條件){知足條件執行的語句} [else {不知足條件執行語句} if(判斷條件1){知足條件1執行語句}else if (判斷條件2{知足條件2時執行語句}else{不 知足上述兩個條件執行語句]
實例1、根據UID判斷系統中用戶是系統用戶仍是普通用戶
[root@centos6 ~]#awk -F: '{if($3<=200){name="system"}else {name="user"} print $1,name}' /etc/passwd root system bin system daemon system adm system lp system sync system shutdown system halt system mail system uucp system operator system games system gopher system ftp system nobody system vcsa system saslauth user postfix system sshd system lin user tcpdump system hacker user dbus system test user apache system
實例2、將20到30的數相加
[root@centos6 ~]#seq 50 |awk '{if($1>=20&&$1<=30){sum+=$1}}END{print sum}' 275
判斷系統中小於300的所有都是系統用戶,其餘的所有爲普通用戶
2.while循環
語法{while (判斷條件){循環語句}},條件爲真時,開始執行循環
awk屬於行之間的循環,他不會對列進行循環,因此若須要對列進行計算和格式化處理,則須要使用awk內置循環來進行
實例1、將每一行的和輸出值終端
[root@centos6 ~]#cat test.txt 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [root@centos6 ~]#awk '{sum=0;i=1;while(i<=NF){sum+=$i ;i++}print sum}' test.txt 55 155
實例2、統計/boot/grub2/grub.conf文件中行首爲linux16行每個字段的字符數
[root@centos7 ~]# awk '/^[[:space:]]+linux/{i=1;while(i<=NF){print $i,length($i);i++}}' /boot/grub2/grub.cfg linux16 7 /vmlinuz-0-rescue-e8e8f687a3b24f13bda5566ae49855e6 50 root=UUID=7b231a1b-a730-40dd-ae89-4d565d07b340 46 ro 2 rhgb 4 quiet 5 net.ifnames=0 13 linux16 7 /vmlinuz-4.15.13.test 21 root=UUID=7b231a1b-a730-40dd-ae89-4d565d07b340 46 ro 2 rhgb 4 quiet 5 net.ifnames=0 13 LANG=en_US.UTF-8 16
i做爲自增項,循環條件爲i<=字段數,length($i)內置函數,用於測量字段的長度
3.do while
語法
do{循環語句}while(判斷條件),該語句與while惟一不一樣就是循環必定執行一次,無論判斷條件是否爲真
4.for循環
語法
for(變量;判斷;變量自增){循環語句},其中()中必須是三部分組成
實例1、該實例和while實現的功能一直,只是寫法不一樣
[root@centos7 ~]# awk '/^[[:space:]]+linux16/{for(i=1;i<=NF;i++){print $i,length($i)}}' /boot/grub2/grub.cfg linux16 7 /vmlinuz-0-rescue-e8e8f687a3b24f13bda5566ae49855e6 50 root=UUID=7b231a1b-a730-40dd-ae89-4d565d07b340 46 ro 2 rhgb 4 quiet 5 net.ifnames=0 13 linux16 7 /vmlinuz-4.15.13.test 21 root=UUID=7b231a1b-a730-40dd-ae89-4d565d07b340 46 ro 2 rhgb 4 quiet 5 net.ifnames=0 13 LANG=en_US.UTF-8 16
break:直接跳出循環
[root@centos6 ~]#cat test.txt 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [root@centos6 ~]#awk '{for(i=1;i<=NF;i++){if($i%2==0){break}print $i}}' test.txt 1 11
由於當前文件中有兩行內容,則顯示兩個數,若是隻有一行內容,則只顯示第一個數,由於當執行到2的時候跳出循環進入下次循環,而11之後則是下次循環,因此還會繼續執行
continue:退出此次循環,進入下次循環、
[root@centos6 ~]#cat test.txt 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [root@centos6 ~]#awk '{for(i=1;i<=NF;i++){if($i%2==0){continue}print $i}}' test.txt 1 3 5 7 9 11 13 15 17 19
當$i的值除以2 餘數爲0則跳出循環,其餘則輸出
next:跳出當前行循環,進入下次行循環
[root@centos6 ~]#seq 10 |awk '{if($1%2==0){next}print $1}' 1 3 5 7 9
next控制的是行間的調過,當該行知足這個條件,則跳出這行循環,進入下次循環
awk中的數組只有關聯數組
1.可使用任意字符串,字符串要使用雙引號括起來
2.若是某數組元素實現不存在,在引用時,awk會自動建立次元素,並將其值初始化爲空字符串
語法
數組名["下標"]="參數"
數組能夠用於統計某個字符串出現過幾回,用來統計次數
實例1、統計access_log文件每個ip的訪問次數
[root@centos6 ~]#awk '{ip[$1]++}END{for(i in ip){print i,ip[i]}}' access_log 172.18.250.183 81 172.18.251.149 158 172.18.0.223 12 172.18.251.21 81 172.18.251.122 52 172.18.254.6 1643 172.18.253.21 74087 172.18.251.150 34 172.18.252.134 514
length():返回指定字符串的長度
[root@centos6 ~]#echo abcde | awk '{print length($1)}' 5
rand():返回0和1之間的隨機數,也就是小數在使用rand()函數時,在前面必須指定種子srand(),若想隨機整數,則須要乘以一個數(根據想要的位數)[root@centos6 ~]#awk 'BEGIN{srand();print int(rand()*10)}'
int()也是函數,它的做用是取整數,當前命令會隨機取10之內的整數
sub(r,s,[t]):對t字符串進行搜索r表示模式匹配的內容,並將第一個匹配的內容替換爲s
gsub(r,s,[t]):對匹配的字符全局替換
[root@centos6 ~]#echo {1..10} | awk 'gsub(" ",":",$0)' 1:2:3:4:5:6:7:8:9:10
將空格全局替換成:
split(s,array,[r]):以r爲分隔符,切割字符串s,而且將切割後的結果保存到array的數組中,第一個索引值爲1
[root@centos6 ~]#awk '{split($5,c,":")};{ip[c[1]]++}END{for (i in ip){print $1,ip[i]}}' netstat.log tcp 13 tcp 3 tcp 1 tcp 1 tcp 1 tcp 1 tcp 1 tcp 1 tcp 1 tcp 1 tcp 1 tcp 1 tcp 1 tcp 1 tcp 15
function name (虛變量1,虛變量2){ 處理動做 處理動做 }
虛變量指的是須要用戶輸入兩個變量,可是傳入函數執行的變量和函數自己變量名不一致,也能夠理解成一種定義格式,必須指定兩個變量才能夠調用該函數
awk程序也能夠寫成腳本,而後當程序須要是,能夠直接調用執行,awk腳本也是須要執行權限,因此在執行以前須要個執行權限
腳本格式
#!/bin/awk -f 腳本內容
實例一
#!/bin/awk -f function biji (x,y){ if(x>y){ max="x>y"} else if (x==y){max="x=y"} else{ max="x<y" } return max } BEGIN{print biji(a,b)} [root@centos6 ~]#awk -v a=7 -v b=7 -f test.awk x=y [root@centos6 ~]#awk -v a=7 -v b=6 -f test.awk x>y [root@centos6 ~]#awk -v a=5 -v b=6 -f test.awk x<y
在awk語句中,也能夠根據需求調用系統的一些命令,可是要結合system內置函數來實現
語法awk BEGIN‘system("系統命令")’