AWK處理日志入門(轉)


 

前言

這兩天自己挽起袖子處理日志,終於把AWK給入門了。其實AWK的基本使用,學起來也就半天的時間,之前總是靠同事代勞,惰性呀。

此文僅為菜鳥入門,運維們請勿圍觀。

下面是被處理的日志的示例,不那么標准,但不標准的日志正是標准的情況。

 

[2015-08-20 10:00:55.600] - [192.168.0.73/192.168.0.75:1080 com.vip.xxx.MyService_2.0 0 106046 100346 90ms 110ms]

 

基本語句

最基本的語句,以空格做分割,提取所需的列:

 

awk '{print $0,$1,$2,$(NF-1),$NF,$NF-$(NF-1)}’ access.log

 

1. 輸入

AWK是針對文件或管道中每行輸入的處理語言。所以也可以從管道輸入:

 

grep “xxx” access.log | awk '{print $1}’

但下面這樣寫就會成為一個Linux老梗的主角,awk不需要不需要cat的。

 

cat access.log | awk '{print $1}'

2.語句定義

可以快速的用單引號’ ’,把所有語句寫成一行。

也可以用-f 指定文件,文件里可以任意換行,增加可讀性和重用性。

所有執行語句用{}括起來,{}的外面是一些高級的東西比如過濾條件,見后。

3. 列引用

$0代表整行所有數據,$1代表第一列(終於不是程序員數數從0開始了)。

NF是個代表總列數的系統變量,所以$NF代表最后一列,還支持$(NF-1)來表示倒數第二列。

還支持列之間的運算,如$NF-$(NF-1)是最后兩列的值相減。

只寫一個print 是 print $0的簡寫,打印整行所有數據。

4. 輸入的列分隔符

默認以空格做分割符,也可以重新指定,下例指定了':'

 

awk -F ':' '{print $1,$2}’ access.log

也可以正則表達式定義多個分割符,下例指定了 '-' 和 ':'

 

awk -F '[-:]' '{print $1,$2}’ access.log

5. 輸出的列間隔

print $1,$2 中間的','逗號,代表打印時第1與第2列之間使用默認分隔符號也就是空格,也可以用” ”來定義其他任意的字符:

 

awk '{print $1 "\t" $2 " - " $3$4xxxxx$5}’ access.log

上例,在第1第2列之間用 tab 分隔,第2第3列之間用" - "分隔,

也可以什么都不寫代表中間沒分隔,比如第3第4列之間,或者亂寫一些字符沒用" "括起來,也等於沒寫,比如第4第5列之間。

 

數字類型,字符串類型

雖然上例最后兩列的值是字符串類型的,帶着ms字樣,看起來不能做算術運算。

但其實兩個列相減時,AWK就會神奇地把它們轉換為純數字。同樣,做累計的時候,sum=sum+$NF,也能自動轉換為數字。

如果想對某個字符列比較是否大於閥值,先把它轉回數字就行了,上一篇文章里的

 

sed "s|ms]||g" access.log | awk ' $NF>100 {print}'

其實可以簡寫成下面的樣子,性能還比使用sed略快:

 

awk ' $NF*1>100 {print}’ access.log

 

awk ' int($NF)>100 {print}’ access.log

 

BEGIN與END語句

BEGIN與END后的語句定義在處理全部文本內容之前與之后的語句。

1.計算累計值和平均值

 

awk '{sum+=$NF} END {print sum, sum/NR}'

上例對每行輸入內容進行最后一列的值的累計,而END后的語句,打印累計結果 和平均值,NR是系統變量代表總行數。

2.打印表頭

還可以定義BEGIN語句打印表頭,定義變量什么的。

 

awk 'BEGIN{print "Date\t\tTime\t\tCost”} {print $1 "\t"$2 "\t" $NF}’ access.log

上例表頭用兩個制表符分隔,內容則用一個制表符分隔,有良好的對齊效果。
 

過濾行

1. 簡單字符匹配

先用grep過濾也是可以的,也可以用awk簡單在執行語句之外的/ /之間定義正則表達式

 

awk '/192.168.0.4[1-5]/ {print $1}’ access.log

等價於

 

grep "192.168.0.4[1-5]” access.log| awk ‘{print $1}

2. 針對某一列的字符匹配

針對第4列的地址段匹配,~ 是字符匹配,!~則是不匹配的意思。

 

awk '$4 ~ /192.168.0.4[1-5]/ {print}'

3. 針對數值的過濾

支持==, !=, <, >, <=, >=

 

awk '$(NF-1)*1==100 {print}'

 

awk '$NF-$(NF-1)>100 {print}'

見前,對於非純數字的字段,可以用算術運算讓它轉回數字。

4. 多條件同時存在

 

awk '($12 >150 || $(13)>250) {print}'

5. 使用if語句

如果邏輯更復雜,可以考慮使用if,else等語句

 

awk '{ if ($(NF-1)*1>100) print}'

 

其他

1.外部傳入參數

比如從外面傳入超時的閥值,注意threshold在命令行中的位置。

 

awk '{if($(NF)*1>threshold) print}' threshold=20 access.log

2.常用函數

最有用是gsub和sub,match,index等。其中gsub將一個字符串替換為目標字符串,可選定整行替換或只替換某一列。

 

awk '{gsub("ms]","",$NF); if( $NF>100 ) print}' access.log

 

一些例子

1.截取日期段內段數據

方式有很多,都是隨着日志格式不同自由發揮。

比如下段截取17:30:30 秒到 17.31:00的數據,先抽取出時分秒三列,再拼成一個數字進行比較

 

awk -F "[ :.]" '$2$3$4>=173030 && $2$3$4<173100 {print}'

也可以匹配某個整點時間, 下例取11點的日志:

 

awk '/[2015-08-20 11:/ {print $1}’ access.log

取11點01分到05分的數據:

 

awk '/[2015-08-20 11:0[1-5]:/ {print $1}’ access.log

2. 找出超時的數據集中發生的時間

第一段找出超時記錄,第二段過濾掉時間戳里的微秒,然后按秒來合並,並統計該秒超時的次數。

 

awk '$(NF)*1>100 {print}’ access.log | awk -F"." '{print $1}' | sort | uniq -c

 

原文地址:http://calvin1978.blogcn.com/articles/awk_accesslog.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM