awk和流編輯器sed在工作原理和用法上有很多類似之處,它們都是檢查輸入數(shù)據(jù)中的行是否匹配指定的模式,如果匹配成功就對(duì)匹配的行執(zhí)行相應(yīng)的操作,重復(fù)這個(gè)過(guò)程指導(dǎo)所有的輸入數(shù)據(jù)都被處理完,因此awk和sed都是面向數(shù)據(jù)流的工具。此外,awk和sed的相似之處還體現(xiàn)在兩者使用的語(yǔ)法式很類似,都是使用正則表達(dá)式匹配來(lái)確定要操作的行。與sed不同的是,awk執(zhí)行的操作要寫在模式后面的花括號(hào){}中。
案例1:顯示出系統(tǒng)中某個(gè)特定用戶(如root用戶)的用戶名、用戶ID以及主目錄。
#提取passwd文件中某一行的三個(gè)字段
$awk –F: ‘/^root:/{PRint $1,$3,$6;}’/etc/passwd
root 0 /root
解析:/etc/passwd文件的各個(gè)字段是由冒號(hào)隔開,而awk的默認(rèn)分隔符是空格,所以通過(guò)命令行選項(xiàng)-F:來(lái)指定;$1,$3,$6是指第一、三、六字段;
案例2:輸出系統(tǒng)中所有用戶的用戶名及相應(yīng)的用戶ID的表格,并在表格的第一行為這兩列數(shù)據(jù)添加標(biāo)題。
具體代碼實(shí)現(xiàn)如下[user.awk]:
#在主循環(huán)開始以前打印標(biāo)題,使下面的數(shù)據(jù)的含義更加明確
print title to clarify the following databefore main loop begin
BEGIN {
printf "%-15s%s/n","USERNAME","UID";
printf"--------------/n";
}
#主循環(huán)開始運(yùn)行
#從/etc/passwd文件中提取用戶名和UID
{
printf "%-15s%s/n",$1,$3;
}
#通過(guò)選項(xiàng)-f指定要運(yùn)行的awk程序
$awk –F: -f user.awk /etc/passwd
案例3:如何顯示出當(dāng)前系統(tǒng)中所有用戶ID大于等于1000的用戶?
#使用比較表達(dá)式,而不是模式匹配
$awk –F: ‘$3>=1000{ printf “User:%-15sUID:%s/n”,$1,$3;}’ /etc/passwd
格式:
expression { actions; }
當(dāng)有多高表達(dá)式時(shí),使用邏輯與&&和邏輯或||把多個(gè)表達(dá)式連接在一起構(gòu)成更復(fù)雜的表達(dá)式,如搜索當(dāng)前系統(tǒng)中所有使用bash和C Shell的用戶:
$awk –F: ‘($7==”/bin/bash”)|| ($7==”/bin/csh”) { printf “User:%-15sUID:%-15sShell:%s/n”,$1,$3,$7; }’/etc/passwd
案例4:
awk 程序中的變量和Shell腳本中的變量很類似,都是用來(lái)存儲(chǔ)一個(gè)值的。通過(guò)在awk程序中定義變量,我們可以更好地控制awk如何處理數(shù)據(jù)。處理用戶自定義的變量以外,awk還預(yù)定義了一些內(nèi)建變量,通過(guò)這些變量我們可以得到很多有用的信息。
總結(jié)awk常用的內(nèi)建變量:
內(nèi)建變量 | 描述 |
FILENAME | awk當(dāng)前讀取數(shù)據(jù)的文件,如果從標(biāo)準(zhǔn)輸入中讀取數(shù)據(jù),變量的值為橫杠-,在BEGIN規(guī)則中變量為空 |
FNR | 當(dāng)前文件中的當(dāng)前行的行號(hào),每讀一行數(shù)據(jù),它讀值就會(huì)加1,在讀取一個(gè)新文件時(shí)會(huì)被設(shè)置為0 |
NR | 所處理的所有記錄的個(gè)數(shù)。每一個(gè)新行被讀,它的值就會(huì)自動(dòng)加1 |
FS | 輸入行的字符分隔符,默認(rèn)值為空格,可以通過(guò)命令行選項(xiàng)-F指定 |
NF | 當(dāng)前記錄中所包含的字段個(gè)數(shù),每次讀入一個(gè)新的記錄,它的值都會(huì)被重現(xiàn)設(shè)置 |
OFS | 輸出時(shí)的字段分隔符,默認(rèn)是一個(gè)空格 |
ORS | 輸出時(shí)的記錄分隔符,默認(rèn)是換行符 |
RS | 輸入時(shí)的記錄分隔符,默認(rèn)是換行符 |
案例2:寫一個(gè)腳本來(lái)統(tǒng)計(jì)文件中的總行數(shù),空白行的行數(shù)及注釋行的行數(shù)。
#!/bin/bash#本腳本需要至少一個(gè)命令行參數(shù)if [ "$#" -eq 0 ]then echo "Usage;" echo -e "/t'basename $0' [ FILE ]...." exit 1fi #處理每一個(gè)命令行參數(shù)for FILE in "$@";do #只有當(dāng)文件是一個(gè)可讀的文件,并且是一個(gè)含有數(shù)據(jù)的普通文件時(shí)才能被本腳本處理 if [ -f "$FILE" ] && [ -r "$FILE" ] && [ -s "$FILE" ] then echo "$FILE:" awk ' #統(tǒng)計(jì)所有的行數(shù) /.*/{ total_lines += 1; } #正則表達(dá)式/.*/匹配所有行,其中點(diǎn)代表一個(gè)任意的字符,而星號(hào)表示0個(gè)或任意個(gè)的星號(hào)前面的字符 #統(tǒng)計(jì)所有的空行數(shù) /^ *$/{ empty_lines += 1; next; } #正則表達(dá)式/^ *$/表示開頭任意個(gè)空格,以$結(jié)尾 #統(tǒng)計(jì)所有的注釋行行數(shù) /^ *#.*$/{ comment_lines += 1; } #正則表達(dá)式/^ *#.*$/表示#前可能有空格,最后以$結(jié)尾 #在主循環(huán)結(jié)束后輸出結(jié)果 END { printf "/tTotal Lines:%s/t/t",total_lines; printf "Empty Lines:%s/t/t",empty_line; printf "Comment Lines:%s/n",comment_lines; } ' "$FILE" else echo "$FILE can not be handled!" fidoneecho "Done."exit 0
案例3:如何打印/etc/passwd文件中的偶數(shù)行?
#!/bin/bashawk ' BEGIN { #在主循環(huán)開始以前制定分隔符為冒號(hào) FS=":"; } #通過(guò)表達(dá)式匹配所有的偶數(shù)行,awk內(nèi)建變量NR來(lái)實(shí)現(xiàn) NR%2 == 0 { print NR,$0; }' /etc/passwdexit 0
案例4:如何處理多行記錄中提取開發(fā)者的姓名和E-mail地址?
#!/bin/bashawk ' BEGIN { # 設(shè)置分隔符為換行符/n FS="/n"; #設(shè)置輸入記錄分隔符為空字符串 RS=""; #設(shè)置輸出字段分隔符為換行符 OFS="/N" #設(shè)置輸出記錄分隔符為兩個(gè)換行符 ORS="/n/n" #打印標(biāo)題 print "The developers of linux Kernel:" print "(N)name,(E)email" print "---------------" } #使用正則表達(dá)式^N過(guò)濾所有無(wú)關(guān)數(shù)據(jù),只對(duì)以字母N起始的記錄塊進(jìn)行處理 /^N/ { print $1,$2; }' CREDITSexit 0
案例5:在上一例子中,我們提取出開發(fā)者的姓名和E-mail地址,如果希望得到每一個(gè)開發(fā)者的姓,也即名字字符串中的最后一個(gè)字段,應(yīng)該怎么做呢?
#!/bin/bashawk ' BEGIN { # 設(shè)置分隔符為換行符/n FS="/n"; #設(shè)置輸入記錄分隔符為空字符串 RS=""; #設(shè)置輸出字段分隔符為換行符 OFS="/N" #設(shè)置輸出記錄分隔符為兩個(gè)換行符 ORS="/n/n" #打印標(biāo)題 print "The developers of Linux Kernel:" print "(N)name,(E)email" print "---------------" } #使用正則表達(dá)式^N過(guò)濾所有無(wú)關(guān)數(shù)據(jù),只對(duì)以字母N起始的記錄塊進(jìn)行處理 /^N/ { #輸出以字母N起始的開發(fā)者的全名 print $1; }#第一個(gè)awk程序的處理結(jié)果會(huì)繼續(xù)發(fā)送第二個(gè)awk程序進(jìn)行處理' CREDITS|awk ' BEGIN { print "The Last Name of Developers:" print "--------------------" } /^N/{ #打印行號(hào)和最后一個(gè)字段,NF表示字段個(gè)數(shù),$NF表示最后一個(gè)字段 print NR,$NF; }'exit 0
案例6:awk不能直接讀取到shell變量,可通過(guò)命令行創(chuàng)建awk變量的方式把shell變量的值傳遞到awk程序中。
格式:
#使用環(huán)節(jié)變量定義awk變量
awk ‘script’ variable1=VALUE1variable2=VALUE2…files…
在awk程序中還可以使用控制語(yǔ)句,包括if語(yǔ)句、while語(yǔ)句、for語(yǔ)句和do-while語(yǔ)句。
awk中的函數(shù)分內(nèi)建函數(shù)和自定義函數(shù)。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注