1. 程式人生 > >Linux三劍客-AWK

Linux三劍客-AWK

兩個 文本分析 計算 amp 流程 選項參數 fff 目標 att

1、什麽是awk

AWK是一種處理文本文件的語言,是一個強大的文本分析工具。有統計和計算功能。

之所以叫AWK是因為其取了三位創始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的 Family Name 的首字符。

參數說明

選項參數說明:

    -F fs or --field-separator fs
    指定輸入文件折分隔符,fs是一個字符串或者是一個正則表達式,如-F:。
    -v var=value or --asign var=value
    賦值一個用戶定義變量。
    -f scripfile or
--file scriptfile 從腳本文件中讀取awk命令。 -mf nnn and -mr nnn 對nnn值設置內在限制,-mf選項限制分配給nnn的最大塊數目;-mr選項限制記錄的最大數目。這兩個功能是Bell實驗室版awk的擴展功能,在標準awk中不適用。 -W compact or --compat, -W traditional or --traditional 在兼容模式下運行awk。所以gawk的行為和標準的awk完全一樣,所有的awk擴展都被忽略。 -W copyleft or --copyleft, -W copyright or
--copyright 打印簡短的版權信息。 -W help or --help, -W usage or --usage 打印全部awk選項和每個選項的簡短說明。 -W lint or --lint 打印不能向傳統unix平臺移植的結構的警告。 -W lint-old or --lint-old 打印關於不能向傳統unix平臺移植的結構的警告。 -W posix 打開兼容模式。但有以下限制,不識別:/x、函數關鍵字、func、換碼序列以及當fs是一個空格時,將新行作為一個域分隔符;操作符**和**=不能代替^和^=;fflush無效。
-W re-interval or --re-inerval 允許間隔正則表達式的使用,參考(grep中的Posix字符類),如括號表達式[[:alpha:]]。 -W source program-text or --source program-text 使用program-text作為源代碼,可與-f命令混用。 -W version or --version 打印bug報告信息的版本。

2、awk的執行流程

其執行過程和sed相似,在我們遇到復雜的語句時,可以離利用執行過程來理解

題目:passwd文件的第二行的第一列和第二列

[root@luffy-001 oldboy]# awk -F ‘:‘ ‘NR==2{print $1,$2}‘ /etc/passwd
bin x

awk 參數 ‘模式{動作}’ 文件

awk 參數 ‘條件(找誰){幹啥}’ 文件

awk執行過程簡圖

技術分享圖片

3、模式匹配:模式與動作

怎麽找到這一行,然後做點什麽

通過正則表達式作為模式

創建測試環境

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

找出包含數字1的行

[root@luffy-001 files]# sed -n ‘/1/p‘ reg.txt 
Zhang Dandan    41117397   :250:100:175
Zhang Xiaoyu    390320151  :155:90:201
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
[root@luffy-001 files]# awk ‘/1/‘ reg.txt 
Zhang Dandan    41117397   :250:100:175
Zhang Xiaoyu    390320151  :155:90:201
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

awk支持的正則表達式

字符功能
+ 指定如果一個或多個字符或擴展正則表達式的具體值(在 +(加號)前)在這個字符串中,則字符串匹配。命令行:

awk ‘/smith+ern/‘ testfile

將包含字符 smit,後跟一個或多個 h 字符,並以字符 ern 結束的字符串的任何記錄打印至標準輸出。此示例中的輸出是:

smithern, harry smithhern, anne

? 指定如果零個或一個字符或擴展正則表達式的具體值(在 ?(問號)之前)在字符串中,則字符串匹配。命令行:

awk ‘/smith?/‘ testfile

將包含字符 smit,後跟零個或一個 h 字符的實例的所有記錄打印至標準輸出。此示例中的輸出是:

smith, alan smithern, harry smithhern, anne smitters, alexis

| 指定如果以 |(垂直線)隔開的字符串的任何一個在字符串中,則字符串匹配。命令行:

awk ‘/allen | alan /‘ testfile

將包含字符串 allenalan 的所有記錄打印至標準輸出。此示例中的輸出是:

smiley, allen smith, alan

( ) 在正則表達式中將字符串組合在一起。命令行:

awk ‘/a(ll)?(nn)?e/‘ testfile

將具有字符串 aealleanneallnne 的所有記錄打印至標準輸出。此示例中的輸出是:

smiley, allen smithhern, anne

{m} 指定如果正好有 m 個模式的具體值位於字符串中,則字符串匹配。命令行:

awk ‘/l{2}/‘ testfile

打印至標準輸出

smiley, allen

{m,} 指定如果至少 m 個模式的具體值在字符串中,則字符串匹配。命令行:

awk ‘/t{2,}/‘ testfile

打印至標準輸出:

smitters, alexis

{m, n} 指定如果 m 和 n 之間(包含的 m 和 n)個模式的具體值在字符串中(其中m <= n),則字符串匹配。命令行:

awk ‘/er{1, 2}/‘ testfile

打印至標準輸出:

smithern, harry smithern, anne smitters, alexis

[String] 指定正則表達式與方括號內 String 變量指定的任何字符匹配。命令行:

awk ‘/sm[a-h]/‘ testfile

將具有 sm 後跟以字母順序從 ah 排列的任何字符的所有記錄打印至標準輸出。此示例的輸出是:

smawley, andy

[^ String] 在 [ ](方括號)和在指定字符串開頭的 ^ (插入記號) 指明正則表達式與方括號內的任何字符不匹配。這樣,命令行:

awk ‘/sm[^a-h]/‘ testfile

打印至標準輸出:

smiley, allen smith, alan smithern, harry smithhern, anne smitters, alexis

~,!~ 表示指定變量與正則表達式匹配(代字號)或不匹配(代字號、感嘆號)的條件語句。命令行:

awk ‘$1 ~ /n/‘ testfile

將第一個字段包含字符 n 的所有記錄打印至標準輸出。此示例中的輸出是:

smithern, harry smithhern, anne

^ 指定字段或記錄的開頭。命令行:

awk ‘$2 ~ /^h/‘ testfile

將把字符 h 作為第二個字段的第一個字符的所有記錄打印至標準輸出。此示例中的輸出是:

smithern, harry

$ 指定字段或記錄的末尾。命令行:

awk ‘$2 ~ /y$/‘ testfile

將把字符 y 作為第二個字段的最後一個字符的所有記錄打印至標準輸出。此示例中的輸出是:

smawley, andy smithern, harry

. (句號) 表示除了在空白末尾的終端換行字符以外的任何一個字符。命令行:

awk ‘/a..e/‘ testfile

將具有以兩個字符隔開的字符 a 和 e 的所有記錄打印至標準輸出。此示例中的輸出是:

smawley, andy smiley, allen smithhern, anne

*(星號) 表示零個或更多的任意字符。命令行:

awk ‘/a.*e/‘ testfile

將具有以零個或更多字符隔開的字符 a 和 e 的所有記錄打印至標準輸出。此示例中的輸出是:

smawley, andy smiley, allen smithhern, anne smitters, alexis

\ (反斜杠) 轉義字符。當位於在擴展正則表達式中具有特殊含義的任何字符之前時,轉義字符除去該字符的任何特殊含義。例如,命令行:

/a\/\//

將與模式 a // 匹配,因為反斜杠否定斜杠作為正則表達式定界符的通常含義。要將反斜杠本身指定為字符,則使用雙反斜杠。有關反斜杠及其使用的更多信息,請參閱以下關於轉義序列的內容。

題目:顯示xiaoyu的姓氏和ID號碼

[root@luffy-001 files]# awk ‘/Xiaoyu/‘ reg.txt 
Zhang Xiaoyu    390320151  :155:90:201
[root@luffy-001 files]# awk ‘/Xiaoyu/{print $1,$2,$3}‘ reg.txt 相當於$0~,$0 在awk中表示這一行,整行記錄
Zhang Xiaoyu 390320151
[root@luffy-001 files]# awk ‘$2~/Xiaoyu/{print $1,$2,$3}‘ reg.txt   波浪線表示包含,第二列包含xiaoyu的行 的第一列,第二列,第三列
Zhang Xiaoyu 390320151

題目:顯示所有以41開頭的ID號碼的人的全名和ID號碼

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

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

[root@luffy-001 files]# awk ‘$3~/[15]$/{print $1,$2}‘ reg.txt 
Zhang Xiaoyu
Wu Waiwai
Wang Xiaoai
Li Youjiu
Lao Nanhai
[root@luffy-001 files]# awk ‘$3~/(1|5)$/{print $1,$2}‘ reg.txt 
Zhang Xiaoyu
Wu Waiwai
Wang Xiaoai
Li Youjiu
Lao Nanhai

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

gsub的用法:

gsub(/目標/,"替換為什麽",第幾列)
gsub(/目標/,"替換為什麽") == gsub(/目標/,"替換為什麽",$0)

[root@luffy-001 files]# sed ‘s#:#$#g‘ reg.txt 
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
[root@luffy-001 files]# awk ‘{gsub(/:/,‘$‘,$4);print}‘ reg.txt 
awk: {gsub(/:/,,$4);print}
awk:           ^ syntax error
awk: fatal: 0 is invalid as number of arguments for gsub
[root@luffy-001 files]# awk ‘{gsub(/:/,"$",$4);print}‘ reg.txt 
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

題目答案:

[root@luffy-001 files]# awk ‘$2~/Xiaoyu/{gsub(/:/,"$",$4);print}‘ reg.txt 
Zhang Xiaoyu 390320151 $155$90$201

特殊模式:BEGIN 和END

BEGIN{} BEGIN裏面的內容,會在awk讀取文件內容之前運行。
測試,計算。

END{}*** END{}裏面的內容,會在awk讀取完文件的最後一行之後運行。
用來顯示最終結果。
先計算,END顯示結果。

[root@luffy-001 files]# awk ‘BEGIN{print "this is kt"} {print NR,$0}‘ reg.txt 
this is kt
1 Zhang Dandan    41117397   :250:100:175
2 Zhang Xiaoyu    390320151  :155:90:201
3 Meng  Feixue    80042789   :250:60:50
4 Wu    Waiwai    70271111   :250:80:75
5 Liu   Bingbing  41117483   :250:100:175
6 Wang  Xiaoai    3515064655 :50:95:135
7 Zi    Gege      1986787350 :250:168:200
8 Li    Youjiu    918391635  :175:75:300
9 Lao   Nanhai    918391635  :250:100:175
[root@luffy-001 files]# awk ‘BEGIN{print "this is kt"} END{print "this is kb"} {print NR,$0}‘ reg.txt 
this is kt
1 Zhang Dandan    41117397   :250:100:175
2 Zhang Xiaoyu    390320151  :155:90:201
3 Meng  Feixue    80042789   :250:60:50
4 Wu    Waiwai    70271111   :250:80:75
5 Liu   Bingbing  41117483   :250:100:175
6 Wang  Xiaoai    3515064655 :50:95:135
7 Zi    Gege      1986787350 :250:168:200
8 Li    Youjiu    918391635  :175:75:300
9 Lao   Nanhai    918391635  :250:100:175
this is kb

題目:統計/etc/services文件裏面的空行數量

[root@luffy-001 files]# awk ‘/^$/{print NR}‘ /etc/services 
22
266
299
320
326
393
461
474
479
486
494
506
512
518
583
584
[root@luffy-001 files]# awk ‘/^$/{i=i+1;print i}‘ /etc/services 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@luffy-001 files]# awk ‘/^$/{i=i+1} END{print i}‘ /etc/services 
16

統計出現多少次 計數
i=i+1 ===> i++

常見用法

##用法一:
awk {[pattern] action} {filenames}   # 行匹配語句 awk ‘‘ 只能用單引號
##用法二:
awk -F  #-F相當於內置變量FS, 指定分割字符
##用法三:
awk -v  # 設置變量
##用法四:
awk -f {awk腳本} {文件名}

4、awk數組:統計與計算

數組怎麽使用?

技術分享圖片

舉個例子:

[root@luffy-001 files]# awk ‘BEGIN{h[110]="張三";h[114]="XXOO";print h[110],h[114]}‘
張三 XXOO

運算符

運算符                         描述
= += -= *= /= %= ^= **=       賦值
?:                           C條件表達式
||                           邏輯或
&&                            邏輯與
~ ~!                         匹配正則表達式和不匹配正則表達式
< <= > >= != ==               關系運算符
空格                           連接
+ -                           加,減
* / %                       乘,除與求余
+ - !                       一元加,減和邏輯非
^ ***                        求冪
++ --                     增加或減少,作為前綴或後綴
$                              字段引用
in                               數組成員

題目:處理以下文件內容,將域名取出並根據域名進行計數排序處理:(百度和sohu面試題)
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@luffy-001 files]# awk -F ‘[/.]+‘ ‘{print $2}‘ url.txt 
www
www
post
mp3
www
post
## 使用h[$2]建立數組,並自加,打印出其中一個
[root@luffy-001 files]# awk -F ‘[/.]+‘ ‘{h[$2]++;print h["www"]}‘ url.txt 
1
2
2
2
3
3
## 答應所有的結果,只是當種類多了之後,沒法操作
[root@luffy-001 files]# awk -F ‘[/.]+‘ ‘{h[$2]++} END{print h["www"],h["post"],h["mp3"]}‘ url.txt 
3 2 1
## awk獨有的循環的功能
[root@luffy-001 files]# awk -F ‘[/.]+‘ ‘{h[$2]++} END{for(pol in h) print pol,h[pol]}‘ url.txt 
www 3
mp3 1
post 2

題目:統計access.log文件中每個ip地址出現的次數
題目:secure系統日誌分析練習
誰在破解你的密碼(Failed password 每個ip地址出現的次數)
分析系統的每個用戶被破解的次數

## 統計IP登錄次數
[root@luffy-001 log]# awk ‘$0~/Accepted/{h[$11]++}END{for(por in h) print por,h[por]}‘ secure
10.0.0.1 3
## 統計每個用戶被破解的次數
[root@luffy-001 log]# awk ‘$0~/FAILED LOGIN/{h[$12]++}END{for(por in h) print por,h[por]}‘ secure
rot, 1
## 統計誰在破解你的密碼(Failed password 每個ip地址出現的次數)
[root@luffy-001 log]# awk -F "[()]" ‘/FAILED/{h[$2]++}END{for(pol in h) print pol, h[pol]}‘ secure
null 1

Linux三劍客-AWK