作用:接收輸入的文本如日誌等每行有一致性的內容,可按照規則進行分析、處理、轉化得到想要的輸出。
普遍用法:
# 分析文件awk ' rule /pattern/ {action} ' filename# 分析輸入ls netstat.log | awk ' rule /pattern/ {action} '相關符號:
•$0 當前記錄•$n 第n個欄位(一般而言,分析的內容每行一個記錄,每列一個欄位),即第n列•NR 當前行數,不斷增加•NF 欄位數•FS 分析內容(輸入欄位)的分隔符•OFS 輸出欄位分隔符•FILENAME 當前輸入文件名•BEGIN 開始前就執行•END 行數遍歷完再執行•邏輯運算符:||、&&、!=、==、>、<、>=、<=
注意:
•awk語句必須被單引號(必須)包圍•單引號內,我的規律總結為:規則、正則直接寫,行為操作使用{}包起來
二、示例說明先創建了一個日誌文件test_awk.log,內容如下,分隔符默認是空格,這裡為了說明分隔符的使用,使用|作為各個欄位的分隔符:
time user ip msg2020-01-01|ronnie|127.0.0.1|this is msg show2020-01-12|littsh|119.119.0.1|login for test2020-02-13|bob|113.12.34.1|I am bob1.簡單的選取time和ip欄位:
# 示例以#作為分隔符,需要聲明分隔符為#,用-F參數指定awk -F "|" '{print $1,$3}' test_awk.log# 用BEGIN在開始分析前執行指定分隔符,用內置變量FS來指定|為分隔符awk 'BEGIN {FS="|"} {print $1,$3}' test_awk.log分析結果為:
time user ip msg2020-01-01 127.0.0.12020-01-12 119.119.0.12020-02-13 113.12.34.1讀取了所有行數和滿足分隔符條件的第一列和第三列。此時,如果不需要第一行,可以使用NR內建變量來根據它來輸入,命令:
awk -F "|" 'NR!=1 {print $1,$3}' test_awk.log意為:NR(類似索引,awk是按行分析)不為1,即不為第一行的內容,才輸出,註:條件NR!=1直接寫在''內,操作才寫在{}內。結果為:
2020-01-01 127.0.0.12020-01-12 119.119.0.12020-02-13 113.12.34.1如果輸出的結果間距太小,不夠美觀,可以用printf方法來進行格式化輸出,和c很像,命令:
awk -F "|" 'NR!=1 {printf "%-15s %-15s\n",$1,$3}' test_awk.log註:上面命令,printf後面接的是雙引號,裡面%s代表字符串,%-15s代表如果沒有滿足15個字符,那麼就右補齊。輸出如下:
2020-01-01 127.0.0.12020-01-12 119.119.0.12020-02-13 113.12.34.1如果說不希望展示127.0.0.1的數據,那麼,可以輸入條件來過濾:
awk -F "|" 'NR!=1 && $3!="127.0.0.1" {printf "%-15s %-15s\n",$1,$3}' test_awk.log輸出:
2020-01-12 119.119.0.12020-02-13 113.12.34.12.利用正則表達式選取: 若想要選擇含有2020-01的內容,那麼,命令如下:
awk -F "|" '/2020-01/ {print $1,$2,$3}' test_awk.log該命令將正則規則寫在''內,選取的是只要含有2020-01的行數,列為欄位時間、名字、ip,輸出為:
2020-01-01 ronnie 127.0.0.12020-01-12 littsh 119.119.0.1如果我想要選取僅僅ip($3)內含有12的行,就需要指定行,命令如下:
awk -F "|" '$3 ~/12/ {print $1,$2,$3}' test_awk.log正則前需要加$3 ~,意味第三列的匹配模式為後面的正則,~表示模式開始。
2020-01-01 ronnie 127.0.0.12020-02-13 bob 113.12.34.13.統計: 如果我想要得出出ip裡面含有12的有多少列,需要用到變量和END,命令如下:
awk -F "|" '$3 ~/12/ {total+=1} END {print "total is",total}' test_awk.log其中,表達式total+=1必須寫在{}內,每次分析一行,都會給total加1,END意思為直到讀取完所有行才執行後面的內容,故,輸出為:
4.awk腳本: 如果要處理的awk的命令比較複雜的,那麼,可以寫在一個文件中test_awk.awk,內容如下:
#!/bin/awk -f
# BEGIN後面必須緊接著{}BEGIN{ FS="|" printf "time user ip count\n" printf "\n" count = 0}{ # if的寫法 if($3!="127.0.0.1" && NR!=1){ count += 1 printf "%-15s %-15s %-15s %-15s\n",$1,$2,$3,count }}END{ printf "##################################################\n"}該段代碼意思為:開始分析前,先修改分隔符為|;之後自定義輸出幾個欄位,每個欄位包括後面的空格總共15個字符,且count是自定義的;之後輸出---的行分割線;自己定義變量count=0;之後,按行分析,如果第三個欄位ip不是127.0.0.1的且不是第一行的,就輸出,且count每次加1;待所有行分析之後,完後再輸出#################,最後結果如下:
time user ip count2020-01-12 littsh 119.119.0.1 12020-02-13 bob 113.12.34.1 2##################################################1.分析性能: 但是涉及性能,需要研究下極端的情況,無窮小或者無窮大時候的情況,就拿日常web的訪問日誌(不同的內容數量)來說,用普通python腳本讀取、正則分析和用awk讀取分析,後續可以來做一個比較。
關於保安小吳