前言
awk的中有很多的控制語句,awk也支持if語句,while語句,for語句等等編程邏輯充的控制語句及數組、函數。
awk的進階無非就是多練。
1.控制語句
(1)if-else語句
語句格式: if(condition) {statments} if (條件) 條件為真 執行{statments}
只有一個語句可以省略{}。組合語句必須加{}if(condition) {statments} else {statements}雙分支語句 if(條件)為真時執行{statments} else否則執行{statrments}
例:顯示系統上某個用戶的ID號大于1000,這是普通用戶,反之則為系統用戶
~]# awk -F: '{if($3>=1000) {printf "Common user: %s\n",$1} else {printf "root or Sysuser: %s\n",$1}}' /etc/passwd
(提示: -F: 是以:為分隔符 $3/etc/passwd 是第三段 printf 格式化輸出 $1/etc/passwd 的第一段 另外這是空模式是每一行都讀取的)
例 顯示shell為/bin/bash的用戶
~]# awk -F: '{if($NF=="/bin/bash") print $1}' /etc/passwd
( 提示NF是字段數 -F:分隔符:)
顯示/etc/fstab 的一行字段數大于五個 ,否則不顯示
~]# awk '{if(NF>5) print $0}' /etc/fstab
(提示:NF是字段數 $本身 也就是取過來的行整行)
顯示磁盤使用的使用率到5%的分區。
~]# df -h | awk -F[%] '/^\/dev/{print $1}' | awk '{if($NF>=5) print $1}'
(提示: -F[%]是以空格分隔 /^\/dev/ 是以/dev/開頭 也就是地址定界。 $NF是取末尾的字段數)
對awk取得的整行或某個字段做條件判斷;
(2) while循環
語法:while(condition) statement
條件“真”,進入循環;條件“假”,退出循環;
while(conditon) {statments} 只有一個語句可以省略{}。組合語句必須加{}
while使用場景:對一行內的多個字段逐一類似處理時使用;對數組中的各元素逐一處理時使用;
顯示每一個符合條件的行,行內的每一個字段,字段本身和字段的個數。條件(統計/etc/grub,conf 以空白開頭后跟kernel的行)
awk '/^[[:space:]]*kernel/{i=1;while(i<=NF) {print $i,length($i); i++}}' /etc/grub.conf
(提示: /^[[::space:]]*kernel/ 以有多個空白的行后跟kernel做地址定界 i=1:知道變量i=1 i<=NF是判斷有多少個字段數 NF是字段數,print $i 是顯示第幾個字段數 , length()內建函數 :返回指定字符串的長度; i++自加 不然都是1了)
把字符數小于7的不予顯示
awk '/^[[:space:]]*kernel/{i=1;while(i<=NF) {if(length($i)>=7){print $i,length($i)}; i++}}' /etc/grub.conf
(3)do-while循環
語法:do statement while(condition)
意義:不管是真是假先執行一遍。至少執行一次循環體
(4) for循環
語法: for(expr1;expr2;expr3) {statements}
expr1 初始化;expr2條件判斷;expr3控制變量不斷的修正
for(variable assignment;condition;iteration process) {for-body}
~]# awk '/^[[:space:]]*kernel/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg
顯示每一個符合條件的行,行內的每一個字段,字段本身和字段的個數。條件(統計/etc/grub,conf 以空白開頭后跟kernel的行)(跟上面差不多 ,只不過是采用for循環)
特殊用法:
能夠遍歷數組中的元素;
語法:for(var in array) {for-body}
(5) switch語句
語法:switch(expression) {case VALUE1 or /REGEXP/: statement; case VALUE2 or /REGEXP2/: statement; …; default: statement}
這個語法意思: 表達式: case value1 值跟表達式匹配 或者是 正則表達式跟表達式匹配。則顯示statment 。。。。。。。默認用default:statement
(6) break和continue
break [n] 跳出N層循環
continue 退出本次循環
(7)next
提前結束對本行的處理而直接進入下一行;這是跟break不一樣的 ,next直接進入下一行的,break是進入下一字段的。
顯示ID為偶數的用戶
awk -F: '{if($3%2!=0) next; print $1,$3}' /etc/passwd
(提示 $3%2!=0 next ID號不等于0 直接跳入下一行 )
2.array(數組)
關聯數組:array[index-expression]在awk 使用最多
index-expression:
delete array[index] 從數組中刪除某個元素
delete array 刪除整個數組
(1) 可使用任意字符串;字符串要使用雙引號;
(2) 如果某數組元素事先不存在,在引用時,awk會自動創建此元素,并將其值初始化為“空串”;
若要判斷數組中是否存在某元素,要使用"index in array"格式進行;
weekdays[mon]="Monday"
例: awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print weekdays["mon"]}
它會顯示那個呢; 你在去掉mon 和tue的雙引號 看看會怎么言
若要遍歷數組中的每個元素,要使用for循環;
for(var in array) {for-body}
例:awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays) {print weekdays[i]}}'
(提示: 定義一個數組weekdays )
注意:var會遍歷array的每個索引;
state["LISTEN"]++
state["ESTABLISHED"]++
顯示netstat -tan 的以tcp開頭的狀態,并做統計
~]# netstat -tan | awk '/^tcp\>/{state[$NF]++}END{for(i in state) { print i,state[i]}}'
(提示: '/tcp\>/做地址定界, state[]數組 )
~]#awk '{ip[$1]++}END{for(i in ip) {print i,ip[i]}}' /var/log/httpd/access_log
練習1:統計/etc/fstab文件中每個文件系統類型出現的次數;
~]# awk '/^UUID/{fs[$3]++}END{for(i in fs) {print i,fs[i]}}' /etc/fstab
(提示:‘/^UUID’地址定界 fs[]數組 )
練習2:統計指定文件中每個單詞出現的次數;
~]# awk '{for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count) {print i,count[i]}}' /etc/fstab
(提示 :count[]是數組 )
3.函數
(1)內置函數
數值處理:
rand():返回0和1之間一個隨機數;
字符串處理:
length([s]):返回指定字符串的長度;
sub(r,s,[t]):以r表示的模式來查找t所表示的字符中的匹配的內容,并將其第一次出現替換為s所表示的內容;
gsub(r,s,[t]):以r表示的模式來查找t所表示的字符中的匹配的內容,并將其所有出現均替換為s所表示的內容;
split(s,a[,r]):以r為分隔符切割字符s,并將切割后的結果保存至a所表示的數組中;
~]# netstat -tan | awk '/^tcp\>/{split($5,ip,":");count[ip[1]]++}END{for (i in count) {print i,count[i]}}'
(2)自定義函數
想加強sed和awk可以看《sed和awk》
原創文章,作者:N19_king,如若轉載,請注明出處:http://www.www58058.com/20275