GUN awk
文本處理三工具:grup,sed,awk grep,egrep,fgrep:文本過濾工具 sed:行編輯器 模式空間,保持空間 awk:報告生成器,格式化文本輸出工具 AWK:(Aho, Weinberger, Kernighan) 報告生成器,格式化文本輸出 有多種版本: New awk( nawk), GNU awk(gawk).linux使用gawk /usr/bin/awk是gawk的鏈接文件,所以gawk也可以叫做awk name:gawk – 模式掃描和處理語言 awk其實是一門編程語言的解釋器,本身也可以說是一門語言,awk支持條件判斷,數組,循環,變量等多個功能,強大到有單獨語言的功能. 基本用法: awk [options] ‘program(編程語言)’ var=value file… awk [options] -f programfile var=value file… awk [options] 'BEGIN{ action;… } pattern{ action;… } END{action;… }' file ... awk程序通常由:BEGIN語句塊、能夠使用模式匹配的通用語句塊、 END語句塊,共3部分組成 program:通常是被單引號或雙引號中 program:PATTERN{ACTION STATRMENTS}:模式{動作語句1;的語句2;.....} 花括號中多語句之間用分號分隔 此處的模式跟sed中的模式不一樣,有地址定界的含義,動作語句無非是讓一個指令對某些數據處理,并額外在指實現些過程式編程語言關鍵字完成某些動作的執行結果的控制,動作語言引用的是awk內置的支持命令,例print,printf(格式化輸出) options: -F 指明輸入時用到的字段分隔符 -v var=value: 自定義變量 處理文本機制: 從指定的文件中,一次讀取一行文本;把讀取的整行文本用事先指定的輸入分隔符切片,分成N個組成部分,分隔符默認為空白,把每一片自動保存在awk自建的變量中.內建變量叫做$1,$2....,文本片有多少,會建立與之相對數量的位置變量.格式化輸出,就是在文本切割成片以后,讓我們僅顯示諸多片段中的某一段,某些段,全部段($0). 還可以對每個片段進行額外的加工處理; 還可以對切割出的片段,進行條件過濾,例,每行文本中的第二片,是否在一個數值范圍內,在的話,就把這行當中的第四段顯示出來; 還可以對每行文本的每個字段做循環,對字段做單獨處理;注意:AWK的循環功能不是在行間循環,Awk本身可以遍歷文件,有循環功能;這里指的循環是在字段間完成遍歷操作.因為一行有N個字段,要逐字段進行處理的話,就必須要用到循環機制來完成 常用輸出命令 1.print print item1,item2... 要點: (1)逗號分隔item (2)輸出的各item可以字符串,數值,當前記錄的字段,變量或awk的表達式; (3)如省略item,相當于print $0 awk '{print}' awk '{print ""}' 打印空白 2.變量 2.1內建變量: FS: input field seperator 指定輸入字段分隔符 OFs:output field seperator指定輸出字段分隔符 RS:input record seperator指定輸入時的換行符 ORS:input record seperator指定輸出時的換行符 NF:number of field 字段數量 注意:NF不加$,在awk內部引用變量無須加$;$NF不是引用變量,而是顯示字段; NR:number of record 文件行數 FNR:各文件計數,文件行數 FILENAME:當前文件名 ARGC:命令行中的參數個數 ARGV:內建數組,保存的是命令行所給定的各參數;
2.2自定義變量: (1)-v var=value 變量名區分字符大小寫 (2)在program中直接定義
3.printf命令 格式化輸出:printf "FORMAT",item1,item2..... 每一項對位放在FORMAT中進行顯示 ,FPRMAT是格式符,會為每一個item占位,留一個特定格式符號占在那里,item會顯示在FORMAT所指定的對應的格式符號的位置上.而不是寫一個item,就放在那里顯示,這就是格式化輸出機制. (1)FORMAT必須給出 (2)不會自動換行,需要顯式給出換行控制符,\n (3)FORMAT中需要分別為后面的每個item指定一個格式化符號; 格式符: %c:顯示字符的ASCII碼 %d,%i:顯示十進制整數 %e,%E:科學技術法數值顯示 %f:顯示為浮點數 %g,%G:以科學計數法或浮點形式顯示數值 %s:顯示字符串 %u:無符號整數 %%顯示%本身
修飾符:每一個格式符都有其修飾符,可以在格式符前面加修飾的符號,用來控制這種格式顯示機制 #[.#]:第一個數字控制顯示的寬度:第二個#顯示小數點后的精度(不是小數可省略): 例: %3.1f %15s -:左對齊 +顯示數值的符號
4.操作符: 算術操作符: x+y x-y x*y x/y x%y x^y -x:賦值,把正數轉換為負數 +x:轉換為數值 字符操作符: 沒有符號的操作符,字符串連接 賦值操作符: = += -= *= /= %= ^= ++ -- 比較操作符: > >= < <= != == 模式匹配符: ~:左邊是否被右側匹配包含 !~:是否不匹配 cat /etc/passwd |awk '$0 ~ /root/'|wc -l cat /etc/passwd |awk '$0 !~ /root/'|wc -l 邏輯操作符: &&:與 ||:或 !:非 函數調用: function_name(argu1,argu2,...) 條件表達式: selector?if-true-expression:if-false-expression 示例: awk -F: '{$3>=1000?usertype="Common User":usertype="Sysadmin or SysUser";printf "%15s:%-s\n",$1,usertype}' /etc/passwd 5 PATTERN:根據pattern條件,過濾匹配的行,再做處理 (1)empty:空模式,匹配每一行 (2)/regular expression/:僅處理能夠模式匹配到的行,需要用/ /括起來 awk '/^UUID/{print $1}' /etc/fstab awk '!/^UUID/{print $1}' /etc/fstab (3)relational expression: 關系表達式;結果有“真”有“假”;結果為“真”才會被處理; 真:結果為非0值,非空字符串 假:結果為空字符串 示例: awk –F: '$3>=1000{print $1,$3}' /etc/passwd awk -F: '$3<1000{print $1,$3}' /etc/passwd awk -F: '$NF=="/bin/bash"{print $1,$NF}' /etc/passwd awk -F: '$NF~/bash$/{print $1,$NF}' /etc/passwd seq 10 | awk 'i=!i (4) line ranges: 行范圍 startline,endline: /pat1/,/pat2/ 不支持直接給出數字格式 awk -F: '/^root/,/^nobody/{print $1}' /etc/passwd awk -F: '(NR>=2&&NR<=10){print $1}' /etc/passwd (5) BEGIN/END模式 BEGIN{}: 僅在開始處理文件中的文本之前執行一次 END{}:僅在文本處理完成之后執行一次 示例: awk -F : 'BEGIN {print "USER USERID"} {print$1":"$3} END{print "end file"}' /etc/passwd awk -F : '{print "USER USERID“;print $1":"$3}END{print "end file"}' /etc/passwd awk -F: 'BEGIN{print " USER UID \n ---------------- "}{print $1,$3}' /etc/passwd awk -F: 'BEGIN{print " USER UID \n ---------------- "}{print $1,$3}END{print "==============\n END "}' /etc/passwd 6.常用的action (1)Expressions (2)control statements:if while等 (3)Compound statements:組合語句: (4)input statements (5)output statememts 7.控制語句 if(condition){statments} if(condition){statments} else {statements} while(condition){statments} do{statments} while(condition) for(expr1;expr2;expr3){statments} break continue next delete array[index] delete array exit { statements } (1)if-else 使用場景:對awk取得的整行或某個字段做條件判斷 示例: awk -F: '{if($3>=1000)print $1,$3}' /etc/passwd awk -F: '{if($NF=="/bin/bash") print $1}' /etc/passwd awk '{if(NF>5) print $0}' /etc/fstab awk -F: '{if($3>=1000) {printf "Common user: %s\n",$1}else{printf "root or Sysuser: %s\n",$1}}' /etc/passwd awk -F: '{if($3>=1000) printf "Common user: %s\n",$1; else printf "root or Sysuser: %s\n",$1}' /etc/passwd df -h|awk -F% '/^\/dev/{print $1}'|awk '$NF>=80{print$1,$5}‘ awk 'BEGIN{ test=100;if(test>90){print "very good"} else if(test>60){ print "good"}else{print "no pass"}}'
(2)while循環 語法:while(condition) statement 條件為真,進入循環,條件為假,退出循環 使用場景:對一行內的多個字段逐一類似處理時使用;對數組中的個元素逐一處理時使用
(3)do-while循環 語法:do{statments} while(condition) 先執行一遍循環體,在進行判斷,是否繼續執行,至少執行一次循環體 思考:下面兩語句有何不同? awk ‘BEGIN{i=0;print ++i,i}’ awk ‘BEGIN{i=0;print i++,i}’
(4)for循環 語法:for (expr1;expr2;expr3) statement for(variable assignment;condittion;iteration process) {statement(for-body)} 特殊用法:能夠遍歷數組中的元素; 語法:for(var in array) {for-body} 示例: awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print$i,length($i)}}' /etc/grub2.cfg
命令性能比較 time (awk 'BEGIN{total=0;for(i=0;i<=10000;i++){total+=i;};print total;}') time(total=0;for i in {1..10000};dototal=$(($total+i));done;echo $total) time(for ((i=0;i<=10000;i++));do let total+=i;done;echo$total)
(5)switch語句(相當于shell的case語句;多重if條件判斷) 使用場景:多用于字符串比較判斷 語法:switch(expression) {case VALUE1 or /REGEXP; statement;case VALUE2 or /REGEXP; statement;...;default:statement} switch 跟上表達式,判斷符合哪個case,case是關鍵字,value是值,REGEXP是正則表達式,如果表達式的值等于value的值或者能被REGEXP所匹配,就執行第一個分支statement;否則跟第二個case向匹配,一直向下,知道匹配成功,最后有默認分支default. (6)break和continue break[n]:跳出N層循環 continue:提前結束本層循環,進入下一輪循環
(7)next 控制awk的內生循環功能 提前結束對本行的處理而直接進入下一行
awk的數組(array) 連續的內存空間,有索引 數字索引數組 自定義索引數組,稱關聯數組,在awk中使用最多 array[index-expression] index-expression: (1)可使用任意字符串,字符串要使用雙引號; (2)如果某數組元素事先不存在,在引用時,awk會自動創建此元素,并將其值初始化為"空串" 若要判斷數組中是否存在某元素,要使用"index in array"格式進行 若要遍歷數組中的每個元素,要使用for循環,注意:var變量會遍歷數組的每個索引,索引次序不會按常規邏輯,除非要人為排序.
如果某數組元素事先不存在,在引用時,awk會自動創建此元素,并將其值初始化為"空串",如果把初始值當做數值,就是當做0來用.如果某個元素不存在,創建后++,就把數值累加;這種使用場景在統計某個字段或數值出現次數時特別有用
統計netstat中的狀態出現次數,用awk取得最后一字段,把最后一字段當做數組的索引,數組隨便取名,例如"state["LISTEN"],每讀取一行就試圖把最后一字段當做索引下標,來對對應的數組元素實行自增操作, 因此索引對應的數組元素是最后字段的出現次數
練習1:統計/etc/fstab文件中每個單詞中出現的次數
練習2:統計/etc/fstab文件中每個文件系統類型出現的次數
awk函數 內置函數 數值處理: rand() :返回0和1之件的一個隨機數 例:awk 'BEGIN{print rand()}' 注意:在第一個awk命令中生成隨機數,相同命令的數值使用第一詞生成的隨機數,可修改
字符串處理: length([s]):返回指定字符串的長度 sub(r,s,[t]):以r表示的模式來查找t所表示的字符中的匹配的內容,并將其第一次出現替換為s多代表的內容,命令結果為命令執行狀態,不輸出命令結果
gsub(r,s,[t]):以r表示的模式來查找t所表示的字符中的匹配的內容,并將其所有出現的均替換為s多代表的內容;
split(s,a,[r]):以r為分隔符,切割字符s,并將切割后的結果保存至a所表示的數組當中,第一個索引值為1 ,第二個索引值為2...
自定義函數 參考文獻:<<sed和AWK>> 格式: function name ( parameter(變量名), parameter, ... ) { statements return expression } 示例: #cat fun.awk function max(v1,v2) { v1>v2?var=v1:var=v2(三目運算) return var } BEGIN{a=3;b=2;print max(a,b)} #awk –f fun.awk
awk中調用shell命令 system參數 空格是awk中的字符串連接符,如果system中需要使用awk中的變量可以使用空格分隔,或者說除了awk的變量外其他一律用""引用起來。 示例: awk BEGIN'{system("hostname") }' awk 'BEGIN{score=100; system("echo your scoreis " score)}'
awk腳本 將awk程序寫成腳本,直接調用或執行 示例: #cat f1.awk if($3>=1000)print $1,$3} #awk -F: -f f1.awk /etc/passwd #cat f2.awk #!/bin/awk –f #this is a awk script {if($3>=1000)print $1,$3} #chmod +x f2.awk #f2.awk –F: /etc/passwd 向awk腳本傳遞參數 格式: awkfile var=value var2=value2... Inputfile 示例: #cat test.awk #!/bin/awk –f {if($3 >=min && $3<=max)print $1,$3} #chmod +x test.awk #test.awk -F: min=100 max=200 /etc/passwd
實戰:
1、 統計/etc/fstab文件中每個文件系統類型出現的次數 # awk '/^UUID/{fs[$3]++}END{for(i in fs) {printi,fs[i]}}' /etc/fstab 2、 統計/etc/fstab文件中每個單詞出現的次數; # awk '{for(i=1;i<=NF;i++){count[$i]++}}END{for(i incount) {print i,count[i]}}' /etc/fstab
原創文章,作者:wencx,如若轉載,請注明出處:http://www.www58058.com/48211