awk 是一種編程語言,用於在linux/nuix下對文本和數據進行處理。數據能夠來自標準輸入、一個或多個文件,或其它命令的輸出。它支持用戶自定義函數和動態正則表達式等先進功能,是linux/unix下的一個強大的編程工具。它在命令行中使用,但更可能是做爲腳原本使用。linux
awk 的處理文本和數據的方式是這樣的,它逐行掃描文件,從第一行到最後一行,尋找匹配的特定模式的行,並在這些行上進行你想要的操做。若是沒有指定處理動做,則把匹配的行顯示到標準輸出(屏幕),若是沒有指定模式,則全部被操做所指定的行都被處理。awk分別表明其做者姓氏的第一個字母。由於它的做者是三個恩,分別是Alfred Aho、Brian Kernighan、Peter Weinberger。gawk是awk的GNU版本,它提供了Bell實驗室和GNU的一些擴展。正則表達式
awk命令兩種使用方式:shell
(1)命令行模式:awk [options] 'commands' file(s)編程
(2)腳本模式:awk [options] -f scriptfile file[s]數組
awk [options] 'commands' file(s) option: -F 定義字段分割符號 -v 定義變量並賦值 command: 1、範圍說明或者正則表達式或者{awk命令語句1;awk命令語句2;} 2、範圍說明部分能夠是BEGIN、END、邏輯表達式或者爲空 3、awk命令語句間用分號間隔 4、引用shell變量時須要用雙引號引發,命令模式都在單引號''裏面 BEGIN{} {} END{} 行處理前 行處理 行處理後 命令格式: awk 'pattern' filename 示例:awk '/root/' /etc/passwd awk '{action}' filename 示例:awk -F: '{print $1}' /etc/passwd awk 'pattern {action}' filename 示例:awk -F: '/root/{print $1,$3}' /etc/passwd
示例:awk 'BEGIN{FS=":"} /root/{print $1,$3}' /etc/passwd command |awk 'pattern {action}' 示例:df -P | grep '/' |awk '$4 > 25000 {print $4}'
字段分割及相關變量緩存
$1,$2,$3...$n:awk中用該順序形式表示files中每行以間隔符號分割的各列的不一樣字段 $0 表示文本自己 NF 表示當前記錄的字段數(列數) $NF 最後一列 $(NF-1) 倒數第二列 FNR/NR 行號 FILENAME 文件名 "\t" 製表符 RS 換行符 "" 打印字符串 FS 定義間隔符 ~ 匹配,與==相比不是精確比較 !~ 不匹配,不精確比較 == 等於,必須所有相等,精確比較 /[0-9][0-9]+/ 兩個或兩個以上數字 -F'[:#/]' 定義三個分隔符
# awk -F: '{print $0}' /etc/passwd //打印文件全部內容 # awk -F: '{print NR, $0}' /etc/passwd /etc/hosts //打印文件全部內容,幷包括行號 # awk -F: '{print FNR,$0}' /etc/passwd /etc/hosts # awk -F: '{print $0,NF}' /etc/passwd //保留記錄的字段數 # awk 'BEGIN{FS=":"}{print $1,$3}' /etc/passwd //輸入字段分隔符,默認爲空格
格式化輸出:bash
print函數 # date |awk '{print "Month: "$2 "\nYear: "$NF}' # awk -F: '{print "username is: " $1 "\t uid is: "$3}' /etc/passwd # awk -F: '{print "\tusername and uid: " $1,$3 "!"}' /etc/passwd # head -5 /etc/passwd|awk -F: 'BEGIN {print "user\thomedir\tshell"RS"***********************"};{print $1"\t"$(NF-1)"\t"$NF};END {print"************END************"}
print函數 # date |awk '{print "Month: "$2 "\nYear: "$NF}' # awk -F: '{print "username is: " $1 "\t uid is: "$3}' /etc/passwd # awk -F: '{print "\tusername and uid: " $1,$3 "!"}' /etc/passwd 參數說明: %s 字符類型 %d 數值類型 佔15字符 - 表示左對齊,默認是右對齊 printf默認不會在行尾自動換行,加\n
任何awk語句都由模式和動做組成。模式部分決定動做語句什麼時候觸發及觸發事件。處理即對數據進行的操做。若是省略模式部分,動做將時刻保持執行狀態。模式能夠是任何條件語句或複合語句或正則表達式。模式包括兩個特殊字段 BEGIN和END。使用BEGIN語句設置計數和打印頭。BEGIN語句使用在任何文本瀏覽動做以前,以後文本瀏覽動做依據輸入文本開始執行。END語句用來在awk完成文本瀏覽動做後打印輸出文本總數和結尾狀態。編程語言
模式能夠是:正則表達式、比較表達式、條件表達式、算術運算符、邏輯操做符和複合模式、範圍模式等。函數
正則表達式:工具
匹配記錄(整行): # awk '/^alice/' /etc/passwd # awk '!/root/' passwd 匹配字段:匹配操做符(~ !~) # awk -F: '$1 ~ /^admin/' /etc/passwd # awk -F: '$NF !~ /nologin$/' /etc/passwd
比較表達式:
比較表達式採用對文本進行比較,只有當條件爲真,才執行指定的動做。比較表達式使用關係運算符,用於比較數字與字符串。
運算符 含義 示例 < 小於 x<y <= 小於或等於 x<=y == 等於 x==y != 不等於 x!=y >= 大於等於 x>=y > 大於 x>y
# awk -F: '$3 == 0' /etc/passwd # awk -F: '$3 < 10' /etc/passwd # awk -F: '$7 == "/bin/bash"' /etc/passwd # awk -F: '$1 == "root" ' /etc/passwd # awk -F: '$1 ~ /admin/ ' /etc/passwd # df -P | grep '/' |awk '$4 > 25000'
條件表達式:
# awk -F: '$3>300 {print $0}' /etc/passwd # awk -F: '{ if($3>300) print $0 }' /etc/passwd # awk -F: '{ if($3>300) {print $0} }' /etc/passwd # awk -F: '{ if($3>300) {print $3} else{print $1} }' /etc/passwd
算術運算:+ - * / %(模) ^(冪2^3)
能夠在模式中執行計算,awk都將按浮點數方式執行算術運算 # awk -F: '$3 * 10 > 500' /etc/passwd
邏輯操做符和複合模式:
&& 邏輯與 a&&b || 邏輯或 a||b ! 邏輯非 !a
# awk -F: '$3 > 50 && $3 <=100' /etc/passwd # awk -F: '$3 == 0 || $3 <=10' /etc/passwd # awk -F: '!($3 == 0 || $3 <=10)' /etc/passwd
條件判斷:
if語句:
//格式 {if(表達式){語句;語句;...}} # awk -F: '{if($3==0) {print $1 " is administrator."}}' /etc/passwd # awk -F: '{if($3>0 && $3<1000){count++;}} END{print count}' /etc/passwd //統計系統用戶數
if...else語句:
//格式 {if(表達式){語句;語句;...}else{語句;語句;...}} # awk -F: '{if($3==0){print $1} else {print $7}}' /etc/passwd # awk -F: '{if($3==0){count++} else{i++}} END{print "管理員個數: "count ; print "系統用戶數: "i}' /etc/passwd
if...else if...else語句:
//格式 {if(表達式1){語句;語句;...}else if(表達式2){語句;語句;...}else if(表達式3){語句;語句;...}else{語句;語句;...}} # awk -F: '{if($3==0){i++} else if($3>999){k++} else{j++}} END{print i; print k; print j}' /etc/passwd # awk -F: '{if($3==0){i++} else if($3>999){k++} else{j++}} END{print "管理員個數: "i; print " 普通用個數: "k; print "系統用戶: "j}' /etc/passwd
循環:
while:
# awk 'BEGIN{i=1; while(i<=10){print i; i++} }' # awk -F: '{i=1; while(i<=10) {print $0; i++}}' /etc/passwd //將每行打印10次
for:
# awk 'BEGIN{for(i=1;i<=5;i++){print i} }' //C風格for awk -F: '{for(i=1;i<=10;i++) print $0}' /etc/passwd //將每行打印10次
數組:
# awk -F: '{username[++i]=$1} END{print username[1]}' /etc/passwd root # awk -F: '{username[i++]=$1} END{print username[1]}' /etc/passwd bin # awk -F: '{username[i++]=$1} END{print username[0]}' /etc/passwd root
數組遍歷:
# awk -F: '{username[x++]=$1} END{for(i=0;i<x;i++) print i,username[i]}' /etc/passwd # awk -F: '{username[++x]=$1} END{for(i=1;i<=x;i++) print i,username[i]}' /etc/passwd # awk -F: '{username[x++]=$1} END{for(i in username) {print i,username[i]} }' /etc/passwd # awk -F: '{username[++x]=$1} END{for(i in username) {print i,username[i]} }' /etc/passwd
練習
1. 統計/etc/passwd 中各類類型shell的數量 # awk -F: '{shells[$NF]++}END{ for(i in shells){print i,shells[i]}}' /etc/passwd 2. 網站訪問狀態統計 <當前時實狀態 netstat> # netstat -ant |grep :80 |awk '{access_stat[$NF]++}END{for(i in access_stat){print i, access_stat[i]}}' # netstat -ant |grep :80 |awk '{access_stat[$NF]++} END{for(i in access_stat ){print i,access_stat[i]}}' |sort -k2 -n |head # ss -an |grep :80 |awk '{access_stat[$1]++} END{for(i in access_stat){print i,access_stat[i]}}' # ss -an |grep :80 |awk '{access_stat[$1]++} END{for(i in access_stat){print i,access_stat[i]}}' |sort -k2 -rn 3. 統計當前訪問的每一個IP的數量 <當前時實狀態 netstat,ss> # ss -an |grep :80 |awk -F":" '!/LISTEN/{ip_count[$(NF-1)]++} END{for(i in ip_count){print i,ip_count[i]}}' |sort -k2 -rn 4. 統計Apache/Nginx日誌中某一天的PV量 <統計日誌> # grep '07/Aug/2012' access.log |wc -l 5. 統計Apache/Nginx日誌中某一天不一樣IP的訪問量 <統計日誌> # grep '07/Dec/2018' access.log |awk '{ips[$1]++} END{for(i in ips){print i,ips[i]} }' |sort -k2 -rn # grep '07/Dec/2018' access.log |awk '{ips[$1]++} END{for(i in ips){print i,ips[i]} }' |awk '$2>100' |sort -k2 6. awk函數 統計用戶名爲4個字符的用戶 # awk -F: '$1~/^....$/{count++; print $1} END{print "count is: " count}' /etc/passwd # awk -F: 'length($1)==4{count++; print $1} END{print "count is: "count}' /etc/passwd 7. 取得網卡IP(除ipv6之外的全部IP) # ifconfig |awk '/[ ]inet[ ]/{print $2}' 8. 得到內存使用狀況 # free -m |awk 'NR==2{print $3*100/$2}' 9. 得到磁盤使用狀況 # df |awk '/\/$/{print $5}' 10. 清空本機的ARP緩存 # arp |awk '!/Address/{print "arp -d " $1}'|bash # arp -n |awk '/^[0-9]/{print $1}' |xargs -I {} arp -d {}