04.21 三劍客之老大awk命令詳解

第一章 awk執行過程

1. awk版本信息

[root@Never-downtime ~]# awk --version
GNU Awk 3.1.7

2. awk參數模式動作
模式既pattem,可以類似理解成sed的模式匹配,可以由表達式組成,也可以是兩個正斜槓之間的正則表達式。
比如NR==1,這就是模式,可以把他理解爲一個條件。
動作即action,是由在大括號裏面的一條或多條語句組成,語句之間使用分號隔開。如下awk使用格式。
這裏寫圖片描述

3. awk執行過程

1讀取一行>>
2根據模式/條件判定是否是要處理的行(NR>=2)>>
3如果不是則讀取下一行,直到文件的結尾>>
4如果是對讀取的行進行動作(action)處理>>
5處理完了繼續讀取文件的下一行 重複操作直至文件末尾。

第二章 awk記錄和字段

1. 行和列
接下來我們給大家帶來兩個新概念記錄和字段,這裏爲了方便大家理解可以把記錄就當做行即記錄==行,字段相當於列,字段==列。

名稱 含義
record 記錄、行
field 域、區域、字段、列

awk默認情況下每一行都是一個記錄(record)
RS即record separator輸入數據記錄分隔符,每一行是怎麼沒的,表示每個記錄輸入的時候的分隔符,即行與行之間如何分割。
NR即number of record記錄(行)號,表示當前正在處理的記錄(行)的號碼。
ORS即output record separator輸出記錄分隔符。
awk使用內置變量RS來存放輸入記錄分隔符,RS表示的輸入的記錄分隔符,這個值可以通過BEGIN模塊重新定義修改。

[root@Never-downtime files]# cat awkfile.txt 
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin

awk 'BEGIN{RS="/"}{print NR,$0}' awkfile.txt

2. awk記錄知識小結
NR(number of record)存放着每個記錄的號(行號)讀取新行時候會自動+1
RS(record separator)是輸入數據的記錄/行標誌,簡單理解就是可以指定每個記錄的結尾標誌。RS作用就是表示一個記錄的結束。
當我們修改了RS的值,最好配合NR行來查看變化,也就是修改了RS的值通過NR查看結果,調試awk程序。
ORS輸出數據的記錄的分隔符。可以通過修改RS的值,然後配合NR(行)來查看變化,也就是修改了RS的值通過NR查看結果,調試awk程序。

3. 字段(列)
每條記錄都是由多個區域(field)組成的,默認情況區域之間的分隔符是由空格(即空格或製表符)來分隔,並且將分隔符記錄在內置變量FS中,每行記錄的區域數保存在awk的內置變量NF中。
這裏寫圖片描述

4. FS與OFS
(1)FS即field separator,輸入字段(列)分隔符。分隔符就是菜刀,把一定字符串切位很多個區域。
(2)awk -F 實際上修改的就是FS的內容,相當於 awk ‘BEGIN{FS=”:”}’
(3)NF即number of fileds,表示一行中列(字段)的個數,可以理解爲菜刀切過一行後,切成了多少份。
(4)OFS輸出字段(列)分隔符。
(5)awk使用內置變量FS來記錄區域分隔符的內容,FS可以在命令行上通過-F參數來更改,也可以通過BEGIN模塊來更改。
(6)然後通過nn 1取第一個區域,2 NF取最後一個區域。
這裏寫圖片描述

5. 記錄與字段(行與列)小結

小結
RS記錄分隔符,表示每行的結束標誌。
NR行號(記錄號)
FS字段分隔符,每列的分隔標誌或結束標誌。
NF就是每行有多少列,每個記錄中字段的數量。
$符號表示取某個列(字段),$1,$2,$NF
NF(number of field)表示記錄中的區域(列)數量,$NF取最後一個列(區域)
FS 字段(列)分隔符, awk -F “:” ===== awk ‘BEGIN{FS=”:”}’
NR number of record 行號
分隔符就是結束標識
記錄與區域,就是所謂的行與列 即(RS,FS)

第三章 awk正則匹配操作符

awk 正則匹配操作符 含義
~ 用於對記錄或區域的表達式進行匹配
!~ 用於表達與~相反的意思

1. 案例
處理文件test.txt內容,將域名取出並根據域名進行計數排序處理

http://www.etiantian.org/index.html
http://www.etiantian.org/1.html
http://post.etiantian.org/index.html
http://mp3.etiantian.org/index.html
http://www.etiantian.org/3.html
http://post.etiantian.org/2.html

[root@Never-downtime files]# awk -F/ '{print $3}' test.txt |egrep -o [a-zA-Z0-9]|sort|uniq -c
      1 3
     12 a
      6 e
      6 g
     12 i
      1 m
     12 n
      8 o
      3 p
      6 r
      2 s
     14 t
      9 w

2. 環境搭建

mkdir -p /server/files/
cat >>/server/files/reg.txt<<EOF
Zhang Dandan    41117397   :250:100:175
Zhang Xiaoyu    390320151  :155:90:201
Meng  Feixue    80042789   :250:60:50
Wu    Waiwai    70271111   :250:80:75
Liu   Bingbing  41117483   :250:100:175
Wang  Xiaoai    3515064655 :50:95:135
Zi    Gege      1986787350 :250:168:200
Li    Youjiu    918391635  :175:75:300
Lao   Nanhai    918391635  :250:100:175
EOF

3. 顯示姓Zhang的人的第二次捐款金額及她的名字

[root@web02-8 files]# awk -F "[ :]+" 'NR<=2{print $2,$(NF-1)}' reg.txt 
Dandan 100
Xiaoyu 90

[root@web02-8 files]# awk -F "[ :]+" '/^Zhang/{print $2,$(NF-1)}' reg.txt 
Dandan 100
Xiaoyu 90

4. 顯示Xiaoyu的姓氏和ID號碼

[root@Never-downtime files]# awk 'NR==2{print $1,$3}' reg.txt 
Zhang 390320151

[root@web02-8 files]# awk '/Xiaoyu/{print $1,$3}' reg.txt 
Zhang 390320151

5. 顯示所有以41開頭的ID號碼的人的全名和ID號碼

[root@web02-8 files]# awk '$3~/^41/{print $1,$2,$3}' reg.txt 
Zhang Dandan 41117397
Liu Bingbing 41117483

6. 顯示所有以一個D或X開頭的人名全名

[root@web02-8 files]# awk '$2~/^[DX]/{print $1,$2}' reg.txt 
Zhang Dandan
Zhang Xiaoyu
Wang Xiaoai

7. 顯示所有ID號碼最後一位數字是1或5的人的全名

[root@web02-8 files]# awk '$3~/[15]$/{print $1,$2}' reg.txt 
Zhang Xiaoyu
Wu Waiwai
Wang Xiaoai
Li Youjiu
Lao Nanhai

[root@web02-8 files]# awk '$(NF-1)~/1$|5$/{print $1,$2}' reg.txt 
Zhang Xiaoyu
Wu Waiwai
Wang Xiaoai
Li Youjiu
Lao Nanhai

8. 顯示Xiaoyu的捐款.每個值時都有以$開頭.如$520$200$135

[root@web02-8 files]# awk 'BEGIN{FS=":" ;OFS="$"}NR==2{print "$"$2,$3,$NF}' reg.txt 
$155$90$201

[root@web02-8 files]# awk -F ":" '/Xiaoyu/{print "$"$2"$"$3"$"$4}' reg.txt 
$155$90$201

[root@web02-8 files]# awk  'NR==2{gsub(/:/,"$");print $NF}' reg.txt 
$155$90$201

9. 顯示所有人的全名,以姓,名的格式顯示,如Meng,Feixue

[root@Never-downtime files]# awk 'BEGIN{OFS=","}{print $1,$2}' reg.txt 
Zhang,Dandan
Zhang,Xiaoyu
Meng,Feixue
Wu,Waiwai
Liu,Bingbing
Wang,Xiaoai
Zi,Gege
Li,Youjiu
Lao,Nanhai

[root@Never-downtime files]# awk '{print $1","$2}' reg.txt 
Zhang,Dandan
Zhang,Xiaoyu
Meng,Feixue
Wu,Waiwai
Liu,Bingbing
Wang,Xiaoai
Zi,Gege
Li,Youjiu
Lao,Nanhai

第四章 BEGIN模式

BEGIN{}模塊在awk讀取文件之前就執行,一般用來定義我們的內置變量(預定義變量,eg,FS,RS),可以輸出表頭
BEGIN模式之前我們有在示例中提到,自定義變量,給內容變量複製等,都使用過。需要注意的是BEGIN模式後面要接一個action動作操作,包含在大括號內。awk必須在對輸入文件進行任何處理前先執行BEGIN裏的動作(action)。
我們可以不要任何輸入文件,就可以對BEGIN模塊進行測試,因爲awk需要先執行完BEGIN模式,纔對輸入文件做處理。BEGIN模式常常被用來修改內置變量ORS、RS、FS、OFS等的值。

1. 讀取文件前執行

[root@Never-downtime files]# awk -F ":"  'BEGIN{print "NAME","UID"}{print $1,$3}'   awkfile.txt  |column -t
NAME      UID
root      0
bin       1
daemon    2
adm       3
lp        4
sync      5
shutdown  6
halt      7
mail      8
uucp      10

2.作用1:定義變量內容
例如RS、ORS、FS/—F 、OFS

[root@Never-downtime files]# awk 'BEGIN{name="hello";print name}'
hello

3. 作用2:計算器

[root@Never-downtime files]# awk 'BEGIN{print 10/3}'
3.33333

4. 取eth0的ip

[root@Never-downtime files]# ifconfig eth0 |awk -F "(addr:)|(Bcast:)" 'NR==2{print $2}'
192.168.56.129

[root@Never-downtime files]# ifconfig eth0 |awk -F "[ :]+" 'NR==2{print $4}'
192.168.56.129

[root@Never-downtime files]# ifconfig eth0 |awk -F "[^0-9.]+" 'NR==2{print $2}'
192.168.56.129

[root@Never-downtime files]# ifconfig eth0|awk 'BEGIN{FS="(addr:)|(Bcast:)"}NR==2{print $2}'
192.168.56.129

[root@Never-downtime files]# ifconfig eth0|awk 'BEGIN{FS="[ :]+"}NR==2{print $4}'
192.168.56.129

[root@Never-downtime files]# ifconfig eth0|awk 'BEGIN{FS="[^0-9.]+"}NR==2{print $2}'
192.168.56.129

第五章 END模式

END在awk讀取完所有的文件的時候,再執行END模塊,一般用來輸出一個結果(累加,屬組結果),也可以是和BEGIN模塊類似的結尾表示信息。

1.統計文件有多少行

[root@web02-8 files]# awk '{i=i+1;print i}' reg.txt 
1
2
3
4
5
6
7
8
9

[root@web02-8 files]# awk '{i=i+1}END{print i}' reg.txt 
9

[root@Never-downtime files]# cat -n reg.txt |tail -1
9   uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin

[root@Never-downtime files]# sed -n 'p' reg.txt |wc -l 
9

第六章 awk執行過程

(1)命令行的賦值(-F或-v)
(2)執行BEGIN模式裏面的內容
(3)開始讀取文件
(4)判斷條件(模式)是否成立
(5)成立則執行對應動作裏面的內容
(6)讀取下一行,循環判斷
(7)直到讀取到最後一個文件的結尾
(8)最後執行END模式裏面的內容

[root@Never-downtime files]# a=1 
[root@Never-downtime files]# b=2
[root@Never-downtime files]# awk 'BEGIN{print a+b}'
0
[root@Never-downtime files]# awk -v a=1 -v b=2 'BEGIN{print a+b}'
3
[root@Never-downtime files]# awk -v a=$(hostname) 'BEGIN{print a}'
Never-downtime

第七章 awk屬組

變量相當於一室的房子,每次只能住一家人,如果想往裏面放很多種不同的內容,或者住不同的家庭,就需要用到多個變量,可以這不是很方便。所以公寓誕生了,即awk數組。
這裏寫圖片描述

[root@Never-downtime files]# awk 'BEGIN{hotel[110]="xioyu";hotel[119]="bingbing";hotel[401]="tandao";for (pol in hotel) print pol,hotel[pol]}'
110 xioyu
401 tandao
119 bingbing

[root@web02-8 files]# awk 'BEGIN{h[110]="xiaoyu";h[119]="bingbing";h[401]="tandao";for (a in h)print a,h[a]}'
119 bingbing
110 xiaoyu
401 tandao

這裏寫圖片描述

awk屬組總結
(1)awk數組是分析日誌最常用的功能,也是玩轉awk必會的部分。
(2)awk數組的名字就像九點的名字一樣,學習的時候我們可以用hotel,h等等,後面再使用的時候要命名規範一些,要不再次使用的時候就不理解了。
(3)awk數組的元素名字就像房間號碼,房間號碼用的一般就是你想要處理的東西,比如統計ip地址,比如統計url。可以把ip,url作爲房間號碼。
(4)遇到awk數組的元素的內容就像房間裏面住的人,一般就是放我們想要的結果,或者計算的結果,即把計算結果放在房間中,
(5)遇到awk數組的處理一般都是進行統計,這時候我們會把最後的結果在END模塊裏面輸出。
(6)輸出awk數組的結果,就是現實房間裏面的內容,即查房。
(7)awk的查房是通過for (pol in hotel)這種形式來完成的,fot表示循環,pol表示警察是一個變量名字,in表示去查房,hotel表示酒店名稱,合起來就是警察去酒店查房, 查完一個繼續查下一個。
(8)在查房過程中pol警察知道房間號碼,也就是說pol變量中的內容就是房間號碼。
(9)要看房間中的內容,首先要知道酒店名稱,然後就是房間號碼即hotel[pol]。
(10)要熟練使用awk數組在開始的時候就要學會一步一步看awk如何執行的即可。

碰到問題先拆解:大象放冰箱一步一步來
第一個里程碑##取出想要的內容
第二個里程碑##創建數組
第三個里程碑##進行統計

擴展案例
假如現在有個文本,格式如下:
a 1
b 3
c 2
d 7
b 5
a 3
g 2
f 6
d 9
即左邊是隨機字母,右邊是隨機數字,要求寫個腳本使其輸出格式爲:
a 4
b 8
c 2
d 16
f 6
g 2
即將相同的字母后面的數字加在一起,按字母的順序輸出。

[root@web02-8 files]# awk '{AA[$1]=AA[$1]+$2}END{for (a in AA)print a,AA[a]}' test.txt 
a 4
b 8
c 2
d 16
f 6
g 2
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章