1. 程式人生 > >淺談awk

淺談awk

space 字母 操作符 出現的次數 and peter 命令 制表符 隨機

awk,文本處理三劍客之一,它的名稱得自於它的創始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首個字母,它不僅是 linux中也是任何環境中現有的功能最強大的數據處理引擎之一。作為一種強大的語言,它具備了一個完整的語言所應具有的幾乎所有精美特性。

基本格式:awk [options] ‘program‘ file…

program:pattern{action statements;..}

pattern和action:

pattern部分決定動作語句何時觸發及觸發事件

BEGIN,END

action statements對數據進行處理,放在{}內指明

print, printf

工作原理

第一步:執行BEGIN{action;… }語句塊中的語句

第二步:從文件或標準輸入(stdin)讀取一行,然後執行pattern{ action;… }語句塊,它逐行掃描文件,從第一行到最後一行重復這 個過程,直到文件全部被讀取完畢。

第三步:當讀至輸入流末尾時,執行END{action;…}語句塊

BEGIN語句塊在awk開始從輸入流中讀取行之前被執行,這是一個 可選的語句塊,比如變量初始化、打印輸出表格的表頭等語句通常 可以寫在BEGIN語句塊中

END語句塊在awk從輸入流中讀取完所有的行之後即被執行,比如 打印所有行的分析結果這類信息匯總都是在END語句塊中完成,它 也是一個可選語句塊

pattern語句塊中的通用命令是最重要的部分,也是可選的。如果 沒有提供pattern語句塊,則默認執行{ print },即打印每一個讀取 到的行,awk讀取的每一行都會執行該語句塊

常用變量和操作符 $0 表示整個當前行 $1 每行第一個字段 NF 字段數量變量 NR 每行的記錄號,多文件記錄遞增 FNR 與NR類似,不過多文件記錄不遞增,每個文件都從1開始 FS BEGIN時定義分隔符 RS 輸入的記錄分隔符, 默認為換行符(即文本是按一行一行輸入)
OFS 輸出字段分隔符, 默認也是空格,可以改為制表符等 ORS 輸出的記錄分隔符,默認為換行符,即處理結果也是一行一行輸出到屏幕 -F‘[:#/]‘ 定義三個分隔符 ~ 匹配,與==相比不是精確比較 !~ 不匹配,不精確比較 == 等於,必須全部相等,精確比較 != 不等於,精確比較 &&  邏輯與 || 邏輯或 awk控制語句 控制語句if-else 語法:if(condition){statement;…}[else statement] if(condition1){statement1}else if(condition2){statement2} else{statement3} 此語句使用場景:對awk取得的整行或某個字段做條件判斷 舉例: awk -F:‘{if($3>=1000)print $1,$3}‘ /etc/passwd (小於1000不做處理,所以沒有else) awk ‘BEGIN{ test=100;if(test>90){print "very good"}else if(test>60){print "good"}else{print "no pass"}}‘ 控制語句while 語法:while(condition){statement;...} 條件“真”,進入循環;條件“假”,退出循環 此語句使用場景:對一行內的多個字段逐一類似處理時使用;對數組中的各元素逐一處理時使用 舉例: awk ‘/^[[:space:]]*linux16/{i=1;while(i<NF){print $i,length($i);i++}}‘ /etc/grub2.cfg 控制語句do-while 語法:do {statement;...}while(condition) 無論真假,至少執行一次循環體 舉例: awk ‘BEGIN{ sum=0;i=0;do{ sum+=i;i++;}while(i<=100);print sum }‘ 控制語句for 語法:for(expr1;expr2;expr3){statement;...} 舉例: awk ‘/^[[:space:]]*linux16/{for(i=1;i<=NF;i++){print $i,length($i)}}‘ /etc/grub2.cfg 控制語句break和continue 舉例: awk ‘BEGIN{sum=0;for(i=1;i<=100;i++){if(i==66)break;sum+=i}print sum}‘ awk ‘BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==0)continue;sum+=i}print sum}‘ awk數組 關聯數組:array[index-expression] index-expression: (1)可以使用任意字符串;字符串要使用雙引號括起來 (2)如果某數組元素事先不存在,在引用時,awk會自動創建此元素,並將其值初始化為“空串” 舉例: weekdays["mon"]="Monday" awk ‘BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print weekdays["mon"]}‘ awk函數 數值處理: rand():返回0和1之間一個隨機數 舉例: awk ‘BEGIN{srand();for (i=1;i<=10;i++)print int(rand()*100) }‘ 字符串處理: length([s]):返回指定字符串的長度 sub(r,s,[t]):對t字符串進行搜索r表示的模式匹配的內容,並將第一個匹配的內容替換為s 舉例: echo "2008:08:08 08:08:08" | awk ‘sub(/:/,"-",$1)‘ gsub(r,s,[t]):對t字符串進行搜索r表示的模式匹配的內容,並全部替換為s所表示的內容 舉例: echo "2008:08:08 08:08:08" | awk ‘gsub(/:/,"-",$0)‘ split(s,array,[r]):以r為分隔符,切割字符串s,並將切割後的結果保存至array所表示的數組中,第一個索引值為1,第二個索引值為2.... 舉例: netstat -tan | awk ‘/^tcp\>/{split($5,ip,":");count[ip[1]]++} END{for (i in count) {print i,count[i]}}‘ 練習: 1、統計/etc/fstab文件中每個文件系統類型出現的次數
awk /^UUID/{fs[$3]++}END{for(i in fs){print i,fs[i]}} /etc/fstab
補充:
/^UUID/:模式匹配以UUID開頭的行 fs[$3]++:定義fs[]為關聯數組下標是每條記錄的第3個字段,數組的值是出現的次數 for(i in fs){print i,fs[i]}:在每條記錄都處理完後,用for循環遍歷數組,打印下標(文件類型)和數組元素值(文件類型出現的次數)
2、統計/etc/fstab文件中每個單詞出現的次數
awk {i=1;while(i<=NF){word[$i]++;i++}}END{for(num in word){print num,word[num]}} /etc/fstab
補充:
用while循環處理每條記錄的每個字段,最主要的是每處理完一個字段要把i置為—,這樣每處理完一個記錄,關聯數組被下一個記錄的每個字段重新賦值
3、提取出字符串[email protected]%9&Bdh7dq+yVixp3vpw中的所有數字
echo "[email protected]%9&Bdh7dq+yVixp3vpw" | awk gsub(/[^[:digit:]]/," ",$0)
補充:
gsub(r,s,[t]):對t字符串進行搜索r表示的模式匹配的內容,並全部替換為s所表示的內容,模式匹配用的是擴展正則表達式
4、解決DOS攻擊生產案例:根據web日誌或者網絡連接數,監控當某個IP並發連接數或者短時間內PV達到100,即調用防火墻命令封掉對應的IP,監控頻率每隔5分鐘。防火墻命令為:iptables -A INPUT -s IP -j REJECT
awk {access[$1]++}END{for(i in access){if(access[i]>=100){print i,access[i]}}} access_log
補充:
監控任務可以寫到計劃任務裏,這裏只使用awk實現過濾(access_log為apache訪問日誌)

謝謝瀏覽,多多評論哦。

淺談awk