GNU awk
全稱:Aho,Weiberger,Kernighan,是三個作者的名字,所以簡稱為awk
awk:報告生成器,主要用來格式化文本輸出的,它能夠實現在處理文本文件時對文檔中的字段有條件的顯示,而且將顯示的結果用非常美觀的文本形式給予輸出。我們所用的awk其實就是gawk,他是一個符號鏈接指向gawk的。
gawk – pattern scanning and processing language:模式掃描及處理語言
awk其實就是一個解釋器,是一個編程語言的解釋器,從本質上來講他也是一個編程語言,支持條件判斷、數組、循環等各種各樣一個編程語言當中幾乎所有的功能。因此我們又可以把gawk稱為一個腳本語言解釋器,他所支持的是一個單獨的腳本編程語言的功能。和bash編程語言一樣,也是過程式編程語言。另外gawk也有自己內置的變量,允許用戶自定義變量。
awk的基本用法:
awk [options] 'program' FILE ... paogram的組成:PATTERN{ACTION STAEMRNTS(動作語句)}:可以有多個語句,語句之間用分號分割。 選項: -F:指明輸入時用到的字段分隔符:從文件中讀取數據時以什么當作分割符 -v var=varlaue:用于實現自定義變量:
awk常用的輸出命令:
1、print
print item1,item2,... 要點: (1)逗號分隔符: (2)輸出的各item可以是字符串,也可以是數值,也可以是當前記錄的字段,變量或awk的表達式 (3)如省略item,相當于print $0(打印整行)
2、變量
內建變量 FS:input field seperator:輸入字段分隔符,默認為空白字符 OFS:output field seperator:輸出字段分隔符,默認為空白字符 RS:input record seperator:輸入時的換行符 ORS:output record seperator:輸出時的換行符 NF:number of field:每一行的字段數量 {print NF},{print $NF} NR:num of record:行數 FNR:各文件分別計數:行數 FILENAME:當前文件名 ARGC:命令行參數的個數 ARGV:是一個數組,保存的是命令行所給定的各參數 自定義變量 (1)-v var=value 變量名區分字符大小寫: (2)在program中直接定義
3、printf
格式化輸出:printf FORMAT,item1,item2,... (1)FORMAT必須給出 (2)不會自動換行,需要顯示給出換行控制符,\n (3)FORMAT中需要分別為后面的每個intem指定一個格式化符號 格式符: %c:顯示字符的ASCII碼 %d,%i:顯示十進制整數 %e,$E:科學計數法數值顯示 %f:顯示為浮點數 %g,%G:以科學計數法或浮點形式顯示數值 %s:顯示字符串 %u:無符號整數 %%:顯示%號自身 修飾符: #[.#]:第一個數字控制顯示的寬度:第二個#顯示小數點后的精度: -:左對齊 +:顯示數值的符號
4、操作符
算術操作符: x+y,x-y,x*y,x/y,x^y,x%y -x +x:轉換為數值: 字符串操作符:沒有符號的操作符,字符串連接的意思 賦值操作符: =,+=,-=,*=,/=,%=,^= ++,-- 比較操作符: >,>=,<,<=,!=,== 模式匹配符: ~:是否匹配 !~:是否不匹配 邏輯操作符: &&,||,! 函數調用: function_name(argu1,argu2,...) 條件表達式: selector?if-true-expression:if-fales-expressiion 示例:格式化顯示/etc/passwd文件中用戶名是普通用戶還是系統用戶還是管理員 awk -F: '{$3>=500?usertype="Common User":usertype="Sysadmin or Sysuser";printf "%15s:%-s\n",$1,usertype}' /etc/passwd
5、pattern
(1)empty:空模式,匹配每一行 (2)/regular expression/:僅處理能夠被此處模式匹配到的行 (3)relational expression:關系表達式:結果有“真”有“假”,結果為“真”才會被處理; 真:結果為非0值為真,非空字符串也為真 (4)line ranges:行范圍,指明起始行,指明結束行 startline,endline:/pat1/,/pat2/ 注意:不支持直接給出數字的格式,須使用如下格式 示例:顯示/etc/passwd中第2行到第10行的用戶名 ~]# awk -F: '(NR>=2&&NR<=10){print $1}' /etc/passwd (5)BENGIN/END模式 BENGIN{}:僅在開始處理文件中的文本之前執行一次: END{}:僅在文本處理完成之后執行一次
6、常用的action
(1)Expressions:表達式 (2)Control statements:控制語句,if,while,for等 (3)Compound statemens:組合語句 (4)input statemens:輸入語句 (5)output statemens:輸出語句
7、控制語句
if(condition) {statmens} if(condition) {statmens} else {statemens} while(condition) {statmens} do {statmens} while(condition) for(expr1;expr2;expr3) {statemens} break continue delete arrar[index] delete array exit { statements} 控制語句說明 (1)if-else 語法:if(condition) statement [else statement] ~]# awk -F: '{if($3>=500) {printf "Common user: %s\n",$1} else {printf "root or Sysuser: %s\n",$1}}' /etc/passwd ~]# awk -F: '{if($NF=="/bin/bash") print $1}' /etc/passwd 示例:顯示/etc/fstab文件中字段數大于5的行 ~]# awk '{if(NF>5) print $0}' /etc/fstab 示例:顯示當前使用空間大于20的設備名稱 ~]# df -h | awk -F[%] '/^\/dev/{print $1}' |awk '{if($NF>=20) print $1}' 使用場景:對awk取得的整行或某個字段做條件判斷 (2)while循環 語法:while(condition) statemnt 條件為真進入循環:條件為假退出循環 使用場景:對一行內的多個字段逐一類似處理時使用:對數組中的各元素逐一處理時使用: ~]# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {print $i,length($i); i++}}' /etc/grub2.cfg ~]# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {if(length($i)>=7) {print $i,length($i); i++}}' /etc/grub2.cfg (3)do-while循環 語法:do statement while(condition) 意義:至少執行一次循環體 (4)for循環 語法:for(expr1;expr2;expr3) statement for(variable assignment;conditiion;iteration process) {for-body} ~]# awk '/^[[:space:]]*llinux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg 特殊用法: 能夠遍歷數組中的元素: 語法:for(var in array) {for-body} (5)switch語句 語法:switch(expression) {case VALUE1 or /REGEXP/: statement;case VALUE2 or /REGEXP2/: statement;...;default: statement} (6)break和continue break [n] continue (7)next 提前結束對本行的處理而直接進入下一行 示例:顯示ID號為偶數的用戶 ~]# awk -F: '{if($3%2!=0) next; print $1,$3}' /etc/passwd
8、array
關聯數組:array[index-expression] index-expreesion (1)可使用任意字符串;字符串要使用雙引號 (2)如果某數組元素事先不存在,在引用時,awk會自動創建此元素,并將其值初始化為“空串” 如要判斷數組中是否存在某元素,要使用“index in array”格式進行 weekdays["mon"]="Monday" 如要遍歷數組中的每個元素,要使用for循環 for(var in array) {for-boby} ~]# awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="tuesday";for(i in weekdays) {print weekdays[i]}}' 注意:var會遍歷array的每個索引 示例:顯示各端口的狀態次數 ~]# netstat -tan | awk '/^tcp\>/{state[$NF]++}END{for(i in state) { print i,state[i]}}' 示例:顯示每個ip地址訪問httpd服務的次數 ~]# 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 練習2:統計指定文件中每個單詞出現的次數; ~]# awk '{for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count) {print i,count[i]}}' /etc/fstab
9、函數
(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)自定義函數
練習:
顯示/etc/fstab文件后五行的第2和第4個字段
]# tail -5 /etc/fstab |awk '{print $2,$4}'
顯示/etc/fstab文件后五行的第2和第4個字段,并且在輸出的行首顯示“ali”字符,在行尾顯示數字“1”。
]# tail -5 /etc/fstab |awk '{print "ali",$2,$4,1}'
顯示/etc/passwd文件中的第1個字段,要求awk內建變量輸入分割符為冒號
]# awk -v FS=':' '{print $1}' /etc/passwd
使用冒號為分割符顯示/etc/passwd文件中的用戶名
]# awk -F: '{print $1}' /etc/passwd
使用輸入分隔符為冒號和輸出分隔符為冒號顯示/etc/passwd文件的第1,3,7字段(以冒號為分割符顯示/etc/passwd中用戶名,UID,shell類型)
]# awk -F':' -v OFS=':' '{print $1,$3,$7}' /etc/passwd
以空格為屬入換行符顯示/etc/passwd文件
]# awk -v RS=' ' '{print }' /etc/passwd
顯示/etc/fstab文件中每行的字段數
]# awk '{print NF}' /etc/fstab
顯示/etc/passwd文件中每行的最后一個字段
]# cat /etc/passwd |awk -F':' '{print $NF}'
分別顯示/etc/fstab和/etc/issue文件的行數
]# awk '{print FNR}' /etc/fstab /etc/issue
格式化顯示/etc/passwd文件中每行的用戶名,UID,shell類型,要求對應顯示username,uid,shelltype
]# awk -F: '{printf "username: %s, uid: %d, shelltype: %s \n",$1,$3,$7}' /etc/passwd
格式化顯示/etc/passwd文件中每行的用戶名,UID,shell類型,要求對應顯示username,uid,shelltype,并且格式輸出寬度為15個字符,左對齊。
]# awk -F: '{printf "username: %-15s, uid: %-15d, shelltype: %-15s \n",$1,$3,$7}' /etc/passwd
顯示/etc/fstab文件中以UUID開頭的行
]# awk '/^UUID/{print }' /etc/fstab
顯示/etc/fstab文件中不以UUID開頭的行
]# awk '!/^UUID/{print }' /etc/fstab
顯示UID大于500的用戶名和UID
]# awk -F: '$3>=500{print $1,$3}' /etc/passwd ]# awk -F: '{if($3>=500)print $1,$3}' /etc/passwd
顯示shell類型為bash的用戶
]# awk -F: '$NF=="/bin/bash"{print $1,$NF}' /etc/passwd ]# awk -F: '$NF~/bash$/{print $1,$NF}' /etc/passwd
原創文章,作者:M20-1馬星,如若轉載,請注明出處:http://www.www58058.com/48725