簡介
AWK是一種優良的文本處理工具。它不僅是 Linux 中也是任何環境中現有的功能最強大的數據處理引擎之一。AWK 提供了極其強大的功能:可以進行樣式裝入、流控制、數學運算符、進程控制語句甚至于內置的變量和函數。它具備了一個完整的語言所應具有的幾乎所有精美特性。實際上 AWK 的確擁有自己的語言:AWK 程序設計語言, 三位創建者已將它正式定義為“樣式掃描和處理語言”。它允許您創建簡短的程序,這些程序讀取輸入文件、為數據排序、處理數據、對輸入執行計算以及生成報表,還有無數其他的功能。最簡單地說, AWK 是一種用于處理文本的編程語言工具。
awk經過改進生成的新的版本nawk,gawk,現在默認linux系統下日常使用的是gawk,用命令可以查看正在應用的awk的來源(ls -l /bin/awk )
awk
gawk – pattern scanning and processing language
基本用法
awk [options] 'program' file1,file2,…..
options常用選項:
-F[]:指定分隔符,使用[]可以指定多個分隔符
-v var=varl:自定義變量
program組成:
PATTERN {ACTION STATEMENT},由語句組成,語句分隔符是";"
ACTION:print,printf
1 print 常用輸出命令
用法:print item1, item2, …
要點:
(1) 逗號分隔符;
(2) 輸出的各item可以字符串,也可以是數值;當前記錄的字段、變量或awk的表達式;
(3) 如省略item,相當于print $0;
注意:
BEGIN
有時候可能在處理數據前運行腳本,比如為報告創建開頭部分,BEGIN關鍵字就是用來做這個的,它會強制gawk在讀取數據前執行BEGIN關鍵字后制指定的程序腳本.
END
跟BEGIN關鍵字類似,END關鍵字允許你指定一個程序腳本,gawk會在讀完數據后執行它的.
示例1:awk程序讀取文本文件并顯示第1數據字段值
awk '{print $1}' test5.txt
示例2:顯示出/etc/fstab 文件里面的第2段和第4段數據,開頭加個hello
tail -5 /etc/fstab | awk '{print "hello",$2,$4}'
2.變量
2.1 內建變量
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:number of record, 行數; FNR:各文件分別計數;行數; FILENAME:當前文件名; ARGC:命令行參數的個數; ARGV:數組,保存的是命令行所給定的各參數;
2.2 自定義變量
(1) -v var=value
變量名區分字符大小寫;
(2) 在program中直接定義
示例3:給test4這個文件用awk 處理之前設置一個開頭部分,處理完成后設置一個結尾部分.
awk 'BEGIN{print "This is the beginning";print "userid shell";print "—— ——";FS=":"}''{print $1,$7}'END'{print "Here is the end"}' test4.txt
示例4 以冒號為字段分隔符顯示/etc/passwd文件里面的第1字段
awk -v FS=":" '{print $1}' /etc/passwd
示例5:處理后顯示出test6.txt的第1,2,3數據字段值
awk 'BEGIN{FS="."}{print $1,$2,$3}' test6.txt
示例6: 通過設置OFS變量,你可以在輸出中使用任意字符來分割字段
awk 'BEGIN{FS=".";OFS="-"}{print $1,$2,$3}' test6.txt
awk -v FS="." -v OFS="-" '{print $1,$2,$3}' test6.txt 這種寫法也可以
示例7: 顯示出/etc/passwd 第1段,第3段和第7段,并且以冒號字段分隔符顯示出來
awk -v FS=":" -v OFS=":" '{print $1,$3,$7}'
示例8:以空白為換行符, 以#號為數據行為分隔符顯示出/etc/passwd
awk -v RS=' ' -v ORS='#' '{print}' /etc/passwd
示例9:顯示/etc/fstab 每一行多少字段
awk '{print NF}' /etc/fstab
示例10:顯示/etc/fstab 最后一個字段
awk '{print $NF}' /etc/fstab
示例11:統計/etc/fstab行數對行直接編號
awk '{print NR}' /etc/fstab
示例12:對/etc/fstab /etc/issue 各文件分別計數,行數
awk '{print FNR}' /etc/fstab /etc/issue
示例13:顯示命令行參數的個數
awk 'BEGIN{print ARGC}' /etc/fstab /etc/issue
示例14:顯示命令行參數數組的第3個參數
awk 'BEGIN{print ARGV[2]}' /etc/fstab /etc/issue
3 printf命令
格式化輸出:printf FORMAT, item1, item2, …
(1) FORMAT必須給出;
(2) 不會自動換行,需要顯式給出換行控制符,\n
(3) FORMAT中需要分別為后面的每個item指定一個格式化符號;
格式符:
%c: 顯示字符的ASCII碼; %d, %i: 顯示十進制整數; %e, %E: 科學計數法數值顯示; %f:顯示為浮點數; %g, %G:以科學計數法或浮點形式顯示數值; %s:顯示字符串; %u:無符號整數; %%: 顯示%自身;
修飾符:
#[.#]:第一個數字控制顯示的寬度;第二個#表示小數點后的精度;
%3.1f
-: 左對齊
+:顯示數值的符號
示例15:顯示/etc/passwd 文件中的第一字段,格式化輸出。
awk -F: '{printf "%s\n",$1}' /etc/passwd
示例16:顯示/etc/passwd 文件中的第1和第3個字段,第1段格式化字符串,第三段格式化十進制整數并且第3段前面要顯示UID:
awk -F: '{printf "%s, UID:%d\n",$1,$3}' /etc/passwd
示例17:顯示/etc/passwd 文件中的第1和第三個字段,第1段格式化字符串并且左對齊,第三段格式化十進制整數并且第3段前面要顯示UID:
awk -F: '{printf "%-15s UID:%d\n",$1,$3}' /etc/passwd
4.操作符
算術操作符: x+y, x-y, x*y, x/y, x^y, x%y -x +x: 轉換為數值; 字符串操作符:沒有符號的操作符,字符串連接 賦值操作符: =, +=, -=, *=, /=, %=, ^= ++, -- 比較操作符: >, >=, <, <=, !=, == 模式匹配符: ~:是否匹配 !~:是否不匹配 邏輯操作符: && || ! 函數調用: function_name(argu1, argu2, ...) 條件表達式: selector?if-true-expression:if-false-expression
示例18:以冒號為字段分隔符,判斷/etc/passwd 文件中的第三個字段,大于500的為顯示為普通用戶,否則其他的顯示為管理員或者是系統用戶。
awk -F: '{$3>=500?usertype="Common User":usertype="Sysadmin or SysUser";printf "%15s:%-s\n",$1,usertype}' /etc/passwd
示例19:以冒號為字段分隔符,找出/etc/passwd 文件中第1個字段為root顯示出來
awk -F":" '$1=="root"{print $1}' /etc/passwd
5 PATTERN
(1) empty:空模式,匹配每一行;
(2) /regular expression/:僅處理能夠被此處的模式匹配到的行;
(3) relational expression: 關系表達式;結果有“真”有“假”;結果為“真”才會被處理;
真:結果為非0值,非空字符串;
(4) line ranges:行范圍,
startline,endline:/pat1/,/pat2/
注意: 不支持直接給出數字的格式
(5) BEGIN/END模式
BEGIN{}: 僅在開始處理文件中的文本之前執行一次;
END{}:僅在文本處理完成之后執行一次;
示例20:匹配/etc/passw文件中結尾是bash的,顯示出第1段和最后一段
awk -F":" '$NF~/bash$/{print $1,$NF}' /etc/passwd
示例21:顯示出test8.txt文件中root開頭一直到myuser10結尾的行
awk -F":" '/^root/,/^myuser10/{print $1}' test8.txt
示例22:匹配/etc/passwd文件中行號大于等于2和小于等于10,顯示出第1個字段
awk -F":" '(NR>=2&&NR<=10){print $1}' /etc/passwd
6.控制語句
if(condition) {statments} if(condition) {statments} else {statements} while(conditon) {statments} do {statements} while(condition) for(expr1;expr2;expr3) {statements} break continue delete array[index] delete array exit { statements }
6.1 if-else
語法:if(condition) statement [else statement]
示例23:判斷如果ID號大于等于500 顯示出來是普通用戶 否則就是管理員或者系統用戶
awk -F: '{if($3>=500) {printf "Common user: %s\n",$1} else {printf "root or Sysuser: %s\n",$1}}' /etc/passwd
示例24:磁盤使用比率大于%10就顯示出來
df -h | awk -F[%] '/^\/dev/{print $1}' | awk '{if($NF>=10) print $1}'
6.2 while循環
語法:while(condition) statement
條件“真”,進入循環;條件“假”,退出循環;
示例25:顯示boot/grub/grub.conf 文件中以空格開頭kernel哪一行字段內容和字符的個數
awk '/^[[:space:]]*kernel/{i=1;while(i<=NF) {print $i,length($i); i++}}' /boot/grub/grub.conf
示例26:顯示boot/grub/grub.conf 文件中以空格開頭kernel哪一行字段內容和字符的個數,字符數大于8的才顯示
awk '/^[[:space:]]*kernel/{i=1;while(i<=NF) {if(length($i)>=7) {print $i,length($i)}; i++}}' /boot/grub/grub.conf
6.3 for循環
語法:for(expr1;expr2;expr3) statement
for(variable assignment;condition;iteration process) {for-body}
示例27:顯示boot/grub/grub.conf 文件中以空格開頭kernel哪一行字段內容和字符的個數(用for循環)
awk '/^[[:space:]]*kernel/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /boot/grub/grub.conf
6.4 next
提前結束對本行的處理而直接進入下一行;
示例28:顯示用戶id 號為偶數的用戶
awk -F: '{if($3%2!=0) next; print $1,$3}' /etc/passwd
7.array
關聯數組:array[index-expression]
index-expression:
(1) 可使用任意字符串;字符串要使用雙引號;
(2) 如果某數組元素事先不存在,在引用時,awk會自動創建此元素,并將其值初始化為“空串”;
若要判斷數組中是否存在某元素,要使用"index in array"格式進行;
示例29:weekdays賦值第一個元素Monday,第二個元素Tuesday,并打印出第一個元素
awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print weekdays["tue"]}'
若要遍歷數組中的每個元素,要使用for循環
示例30:weekdays賦值第一個元素Monday,第二個元素Tuesday,并且都打印出來
awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays) {print weekdays[i]}}'
示例31:netstat -tan 統計tcp狀態出現了多少次
netstat -tan | awk '/^tcp\>/{state[$NF]++}END{for(i in state) { print i,state[i]}}'
示例32:統計/var/log/httpd/access_log 文件中每個IP訪問多少次
awk '{ip[$1]++}END{for(i in ip) {print i,ip[i]}}' /var/log/httpd/access_log
8.函數
8.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所表示的數組中;
原創文章,作者:liangkai,如若轉載,請注明出處:http://www.www58058.com/12129