awk用法詳解

1、awk介紹

  awk是文本三劍客之一,其實awk是一種語言,該語言的創始者定義爲」生成報表和格式化文本輸出「awk有不少種版本,這裏介紹的是GUN awk(gawk)linux

2、awk工做原理

  第一步:執行BEGIN{action}語句塊中的語句,該語句塊不依賴於文件,awk在執行是,將在讀取文件以前執行該語句中的語句塊,經常使用語變量的初始化,打印輸出表格的表頭。
  第二步:從文件、標準輸入、上一條命令輸出結果輸入地區一行,而後進行pattern{aciton}語句塊,它將逐行掃描文件,從第一行到最後一行。若沒有提供pattern語句,則默認執行打印{print},即打印每個讀取到的行。
  第三步:當讀至文件最後時,執行END{action}語句塊。一般用於彙總在pattern語句中執行的過程正則表達式

3、awk基本用法

選項
-F"指定分隔符"
-v 自定義變量:定義變量
      
awk {print} file
awk將把file文件中的每一行都讀取一遍,而後輸出在終端上
輸入內置變量在文本中表明以下圖所示
awk用法詳解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 ~]#  

awk用法詳解
實例一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

4、awk內置變量

  awk命令的print打印內容也能夠不與文件有關,若沒有關係,則表示文件有多少行內容,就會打印本身所指定的內容,而在awk中,處理動做中的字母若不用" "引上則表示使用變量,因此若須要輸出字符串則須要用「 」引上。數字則不須要。
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

5、printf格式化輸出

  在輸出內容時,print輸出只能輸出規定格式的內容,不能自定義格式,因此想要讓輸出結果根據本身所須要的格式輸出就須要用printf來定製格式
printf使用格式
awk ‘{printf "格式1 格式 ",$1,$2}’,格式必須和須要輸出的列一一對應
awk用法詳解
實例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

6、awk運算符

  awk也能夠進行數字間的運算,不但支持整數,並且支持小數
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

7、賦值運算

在賦值操做符中,sum+=i,就至關於sum=sum+i,
awk用法詳解
實例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變量將自增幾回

8、模式匹配

  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

  因所搜內容中也包含 」 / 「 因此須要將搜索內容用雙引號引發來

9、比較操做符

awk用法詳解

10、邏輯操做符

&&:表示同時知足兩個條件
||:表示知足兩個條件中的一個便可
!:表示取匹配結果的反值
實例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

11、條件表達式(三目表達式)

  經常使用於只有兩種狀況下的判斷,若是狀況過多,將不適合使用三目表達式來選擇
語法:判斷條件?條件爲真時執行語句:條件爲假時執行語句
實例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

12、PATTERN模式搜索

  該模式下也支持擴展正則表達式,支持模糊搜索
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

十3、awk控制語句

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

十3、循環控制語句

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控制的是行間的調過,當該行知足這個條件,則跳出這行循環,進入下次循環

十3、awk數組

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

十4、awk內置函數

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

十5、awk自定義函數,腳本調用

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

十6、system命令

  在awk語句中,也能夠根據需求調用系統的一些命令,可是要結合system內置函數來實現
語法
awk BEGIN‘system("系統命令")’

相關文章
相關標籤/搜索