AWK學(xué)習(xí)筆記

學(xué)習(xí)思路:?
AWK命令行書寫由BEGEN Program END三部分構(gòu)成?
BEGEN:在AWK讀取輸入流文本行處理之前執(zhí)行,用于初始化變量、定義輸出表頭信息Program:定義如何處理讀的數(shù)據(jù),由兩部分構(gòu)成:pattern{action statements;..},由模式和動作構(gòu)成,匹配模式則執(zhí)行動作。END在文件逐行處理完成后執(zhí)行END語句,用于統(tǒng)計結(jié)果、生成報告處理流程:?
AWK將處理對象視為二維表逐行讀取逐行處理,默認(rèn)以空白符作為分隔符(可以使用?-F指定分隔符),將文件內(nèi)容分隔為多個域(可以理解為列或字段),一行稱為一條記錄,每條記錄由多個字段構(gòu)成。這些行與列被映射成了AWK的內(nèi)置變量(可以通過-v選項自定義變量),因此用戶就可以通過這些內(nèi)置變量來定位處理對象中的內(nèi)容進(jìn)行處理,簡單理解為:基于行讀取、基于列進(jìn)行處理并輸出。?
語法:?
awk [options] 'program' var=value file…?
awk [options] -f programfile var=value file…?
awk [options] 'BEGIN{action;… }pattern{action;… }END{action;… }' file ...?
每個語句塊都有?
常用選項?
-F "分隔符"?用于指定讀取輸入流文本行中用到的字段分隔符,如果不指則默認(rèn)以空白符為分隔符,并自動壓縮連續(xù)的多個空白符視為一個空白符。?
-f file?從指定文件中讀取通用語句塊?
-v var=value?用于變量賦值?
內(nèi)置變量:?
AWK將處理對象視為二維表逐行讀取,逐行處理,一行為一條記錄,一列為個字段,行與列被映射成了AWK的內(nèi)置變量,所以用戶才可以像處理二維表格一樣處理數(shù)據(jù)。因此AWK的常用內(nèi)置變量也就以行和列的維度就進(jìn)行定義。?
行列維度內(nèi)置變量:?AWK將讀入的文本行以指定分隔符分割為多個列,分別映射為內(nèi)置變量$1,$2,$3...$n,即$1代表第1列,$2代表第2列,以此類推。注意:$0代表所有列,如果語句塊中沒有定義action動作則默認(rèn)動作為print $0,即打印所有列。?
NF:代表被分隔的字段數(shù),即列數(shù)NR:?一行為一條記錄,行號FNR:AWK可以將多個文件作為輸入流,如果希望每個文件分別輸出獨(dú)立的行號則用FNRFILENAME:AWK可以將多個文件作為輸入流,如果希望輸出行中輸出文件名則用FILENAME分隔符:?
AWK處理輸入流時可以用-F選項指定分隔符,但一定會滿足用戶的使用需求,例:在打印輸出時,打印輸入時用的分隔符,就需要手動指定很麻煩,AWK同樣想到了用戶的這一需求,提供了分隔符相關(guān)的內(nèi)置變量。AWK的處理流程就是輸入流處理后生成輸出流,所以分隔符也就有了輸入分隔符、輸出分隔符。?
記住幾個單詞:F:Field S:Separated O:output R:recordFS:輸入分隔符OFS:輸出分隔符RS:輸入記錄分隔符ORS:輸出記錄分隔符FNR:各文件分別計數(shù),記錄號FILENAME:當(dāng)前文件名其它變量?
ARGC:命令行參數(shù)的個數(shù)?
ARGV:數(shù)組,保存的是命令行所給定的各參數(shù)?
自定義變量?
自定義變量一般用于數(shù)據(jù)輔助處理(如控制語句),報表輸出美化等。自定義變量有兩種定義方式:?
-v選項定義:無事先聲明,直接寫在program語句塊中。格式化輸出?
AWK的強(qiáng)項就是報表輸出功能,printf命令可以對處理后的數(shù)據(jù)進(jìn)行格式化輸出,起到美化報表的效果。在格式化輸出過程中要注意以下幾點:?
必須指定FORMA不會自動換行,需要顯式給出換行控制符\nFORMAT中需要分別為后面每個item指定格式符格式符?
%c:顯示字符的ASCII碼%d, %i:顯示十進(jìn)制整數(shù)%e, %E:顯示科學(xué)計數(shù)法數(shù)值%f:顯示為浮點數(shù)%g, %G:以科學(xué)計數(shù)法或浮點形式顯示數(shù)值%s:顯示字符串%u:無符號整數(shù)%%:顯示%自身修飾符?
#[.#]?第一個數(shù)字控制顯示的寬度;第二個#表示小數(shù)點后精度,%3.1f-左對齊(默認(rèn)右對齊)?%-15s+顯示數(shù)值的正負(fù)符號?%+d例:?
指定輸出$1對應(yīng)的輸出修飾為左對齊,輸出域?qū)挾葹?0個字符,$3輸出域?qū)挾葹?0個字符,并換行?
awk -F: '{printf "%-20s %10d\n",$1,$3}' /etc/passwd?
指定Username:之后輸出$1,格式為左對齊,輸出域?qū)挾葹?5個字符,UID:之后輸出$3?
awk -F: '{printf "Username: %-15s,UID:%d\n",$1,$3}' /etc/passwd?
AWK中的操作符?
1.?算術(shù)操作符?
注意:算術(shù)運(yùn)行表達(dá)式輸寫時變量不需要加$符號引用,直接輸寫?
x+y, x-y, x*y, x/y, x^y, x%y-x:轉(zhuǎn)換為負(fù)數(shù)+x:將字符串轉(zhuǎn)換為數(shù)值2.?賦值操作符?
注意:要注意在輸寫自加自減賦值表達(dá)式時,i++與++i的區(qū)別?
=, +=, -=, *=, /=, %=, ^=,++, --i++?先賦值,再自加,例在循環(huán)語句中i=0,A=i++,則A的結(jié)果為0,i的結(jié)果為1++i?先自加,再賦值,例在循環(huán)語句中i=0,A=++i,則A的結(jié)果為1,i的結(jié)果為13.?比較操作符?
注意:在應(yīng)用的時候需要注意==與=的輸寫,有時候疏忽可能會出現(xiàn)書寫錯誤。?
==, !=, >, >=, <, <=例:顯示$3字段等于0的行?
[root@Centos8 ~]#awk -F: '$3==0{print $1,$3}' /etc/passwd4.?模式匹配符?
~:左邊是否和右邊匹配,意為:包含!~:是否不匹配 意為:不包含例:?
awk '$1 ~ "^root"' /etc/passwd?文件中第一字段是否包含rootawk '$0 !~ /root/' /etc/passwd?文件不包含root的行5.?邏輯操作符?
與:&&?意為:并且或:||?意為:或者非:! ?意為:取反例:基于UID過濾顯示用戶?
awk -F: '$3>=0 && $3 <=500{print $1,$3}' /etc/passwdawk -F: '$3==0 || $3>=1000 {print $1},$3' /etc/passwdawk -F: '!($3>=500) {print $1,$3}' /etc/passwd6.條件表達(dá)式(三目表達(dá)式)?
語法:selector?if-true-expression:if-false-expression?
selector:判斷條件if-true-expression:如果為真則執(zhí)行該語句if-false-expression:如果為假則為執(zhí)行該語句例:條件賦值?
awk -F: '$3>=1000?usertype="common user":usertype="sysuser";prin $1,$3' /etc/passwdAWK中的模式?
從輸入流中讀取行,并基于模式匹配,如果滿足條件則執(zhí)行相應(yīng)的處理。?
空模式:如果未指定:匹配每一行正則表達(dá)式:/regular expression/:僅處理能夠模式匹配到的行,需要用/ /括起來關(guān)系表達(dá)式:結(jié)果為“真”才會被處理,非0非空即為真。行范圍匹配:起始位置,結(jié)束位置;/pattern1/,/pattern2/?不支持直接給出數(shù)字格式,pattern可以是正則表達(dá)式BEGIN/END模式:例:?
匹配以root開頭的行到以nobody開頭的行之間的所有行?
awk -F: '/^root\>/,/^nobody\>/{print $1}' /etc/passwd?
控制語句?
AWK中控制語名輸寫原則:?
1.?控制語句通體被大括號{}包裹2.?判斷條件由小括號()包裹3. action作為控制語句了執(zhí)行語句塊,為了邏輯清晰建議action由{}包裹1. if條件判斷?
語法1:if與else分體輸寫,用分號分隔:?
'{if(condition) {statements;…};else {statements;…}}' if與else用分號分隔,然后整個語塊被{}包裹例:awk -F: '{if($3>=1000){print "common:",$1} else {print "sysuser:",$1}}' /etc/passwd?
語法2:if與else合體輸寫,不用分號分隔?
'{if(condition) {statements;…} else {statements;…}}' if與else不用分號分隔,然后整個語塊被{}包裹例:awk -F: '{if($3>=1000) {print "Common user:",$1} else {print "root or Sysuser:",$1}}' /etc/passwd?
語法3:if嵌套?
'{if(condition) {statements;…} else if(condition) {statements;…}else {statements;…}}''{if(condition) action...;else if(condition) action...;else action...}' if else語句塊之間用分號分隔例:awk 'BEGIN{test=100;if(test>90){print "very good"} else if(test>60){ print "good"}else{print "no pass"}}'?
例:awk 'BEGIN{test=10;if(test>80)print "very Good";else if(test>60)print "Good";else print "no pass"}'?
2. for循環(huán)?
for(expr1;expr2;expr3) {statements;…}?
例:awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg?
3. while循環(huán)?
語法:while(conditon) {statments;…}?
例: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)>=10){print $i,length($i)}; i++}}' /etc/grub2.cfg?
4. do...while?
do...while與while的區(qū)別:do...while雁過拔毛不管條件滿不滿足至少執(zhí)行一次;while在條件不滿足時可以一次都不執(zhí)行?
語法:do {statements;…} while(condition)?
例:awk 'BEGIN{ total=0;i=0;do{ total+=i;i++;}while(i<=100);print total}'?
了解更多網(wǎng)絡(luò)知識關(guān)注:http://www.vecloud.com/