AWK增强的文本处理shell特征--AWK完全手册
AWK這是一個(gè)很好的文字處理工具。
它不僅 Linux 中也是不論什么環(huán)境中現(xiàn)有的功能最強(qiáng)大的數(shù)據(jù)處理引擎之中的一個(gè)。
本文主要摘錄池中龍寫的Unixawk使用手冊(cè)(第二版),對(duì)當(dāng)中內(nèi)容略微修改。感謝作者的分享。
目 錄 1
0作者的話 2
1awk的調(diào)用方式 3
2awk的語(yǔ)法 4
3awk的記錄、字段與內(nèi)置變量 5
4awk的內(nèi)置函數(shù) 5
5在命令行使用awk 6
6awk的變量 7
7運(yùn)算與推斷 7
8awk的流程控制 8
8.1BEGIN和END: 8
8.2流程控制語(yǔ)句 9
8.2.1if...else語(yǔ)句: 9
8.2.2while語(yǔ)句 9
8.2.3do-while語(yǔ)句 10
8.2.4for語(yǔ)句 10
9awk中的自己定義函數(shù) 10
10awk高級(jí)輸入輸出 12
10.1讀取下一條記錄: 12
10.2簡(jiǎn)單地讀取一條記錄 12
10.3關(guān)閉文件: 13
10.4輸出到一個(gè)文件: 13
10.5輸出到一個(gè)命令 13
10awk與shellscript混合編程 14
10.1awk讀取Shellscript程序變量 14
10.2將shell命令的運(yùn)行結(jié)果送給awk處理 14
10.3shell script程序讀awk的運(yùn)行結(jié)果 15
10.4在awk中運(yùn)行shell命令行----嵌入函數(shù)system() 15
附錄 16
附1awk的常規(guī)表達(dá)式元字符 16
附2awk算術(shù)運(yùn)算符 16
附3awk同意的測(cè)試 17
附4awk的操作符(按優(yōu)先級(jí)升序排列) 17
附5awk內(nèi)置變量(提前定義變量) 18
附6awk的內(nèi)置函數(shù) 18
參考資料 19
0作者的話
《UNIXAWK使用手冊(cè)》是我?guī)讉€(gè)月前的作品了,回過頭來(lái)看,這篇文章實(shí)在是非常粗燥,因當(dāng)時(shí)我寫作并上傳這個(gè)作品時(shí)實(shí)在是太忙了,沒有對(duì)文章的質(zhì)量進(jìn)行非常好的檢查,心里老認(rèn)為有愧于網(wǎng)友的厚愛。于是趁閑趕忙重寫一遍,盡管不一定會(huì)有非常大的改觀,但質(zhì)量是肯定要好一點(diǎn)的。唯如此。我的良心上才好受一點(diǎn)。呶,以下就是我的改動(dòng)稿,各位老友請(qǐng)與第一版相比一下。看是否有所進(jìn)步。
這次改寫仍然保留了原有的風(fēng)格:正文由淺入深,文后附上了大量的相關(guān)資料,這樣做的原因是為了滿足各種用戶的需求。這在第一版中已經(jīng)說(shuō)過了。
這次基本的改變是在內(nèi)容上,添加了非常多新內(nèi)容。并添加了演示樣例。以幫助讀者理解當(dāng)中的內(nèi)容,附錄也補(bǔ)充了很多新的資料。當(dāng)然讀者要真正地掌握awk,只讀了本文是不夠的。還必須有上機(jī)實(shí)習(xí)這一步。值得提醒大家的是,awk有非常多版本號(hào)。并且各個(gè)版本號(hào)之間存在著一些區(qū)別。因此,在使用awk曾經(jīng)最好參考一下你使用的系統(tǒng)的聯(lián)機(jī)幫助。
什么是awk?
你可能對(duì)UNIX比較熟悉,但你可能對(duì)awk非常陌生。這一點(diǎn)也不奇怪,的確,與其優(yōu)秀的功能相比,awk還遠(yuǎn)沒達(dá)到它應(yīng)有的知名度。awk是什么?與其他大多數(shù)UNIX命令不同的是,從名字上看。我們不可能知道awk的功能:它既不是具有獨(dú)立意義的英文單詞。也不是幾個(gè)相關(guān)單詞的縮寫。其實(shí),awk是三個(gè)人名的縮寫。他們是:Aho、(Peter)Weinberg和(Brain)Kernighan。正是這三個(gè)人創(chuàng)造了awk---一個(gè)優(yōu)秀的樣式掃描與處理工具。
AWK的功能是什么?與sed和grep非常相似,awk是一種樣式掃描與處理工具。但其功能卻大大強(qiáng)于sed和grep。awk提供了極其強(qiáng)大的功能:它差點(diǎn)兒能夠完畢grep和sed所能完畢的所有工作。同一時(shí)候,它還能夠能夠進(jìn)行樣式裝入、流控制、數(shù)學(xué)運(yùn)算符、進(jìn)程控制語(yǔ)句甚至于內(nèi)置的變量和函數(shù)。它具備了一個(gè)完整的語(yǔ)言所應(yīng)具有的差點(diǎn)兒所有精美特性。
實(shí)際上。awk的確擁有自己的語(yǔ)言:awk程序設(shè)計(jì)語(yǔ)言。awk的三位創(chuàng)建者已將它正式定義為:樣式掃描和處理語(yǔ)言(注:這里的樣式指pattern)。
為什么使用awk?
即使如此。你或許仍然會(huì)問,我為什么要使用awk?
使用awk的第一個(gè)理由是基于文本的樣式掃描和處理是我們常常做的工作,awk所做的工作有些象數(shù)據(jù)庫(kù),但與數(shù)據(jù)庫(kù)不同的是。它處理的是文本文件,這些文件沒有專門的存儲(chǔ)格式。普通的人們就能編輯、閱讀、理解和處理它們。
而數(shù)據(jù)庫(kù)文件往往具有特殊的存儲(chǔ)格式。這使得它們必須用數(shù)據(jù)庫(kù)處理程序來(lái)處理它們。既然這樣的類似于數(shù)據(jù)庫(kù)的處理工作我們常常會(huì)遇到,我們就應(yīng)當(dāng)找到處理它們的簡(jiǎn)便易行的方法。UNIX有非常多這方面的工具,比如sed、grep、sort以及find等等。awk是當(dāng)中十分優(yōu)秀的一種。
使用awk的第二個(gè)理由是awk是一個(gè)簡(jiǎn)單的工具,當(dāng)然這是相對(duì)于其強(qiáng)大的功能來(lái)說(shuō)的。
的確,UNIX有很多優(yōu)秀的工具,比如UNIX天然的開發(fā)工具C語(yǔ)言及其延續(xù)C++就非常的優(yōu)秀。但相對(duì)于它們來(lái)說(shuō)。awk完畢相同的功能要方便和簡(jiǎn)捷得多。這首先是由于awk提供了適應(yīng)多種須要的解決方式:從解決簡(jiǎn)單問題的awk命令行到復(fù)雜而靜止的awk程序設(shè)計(jì)語(yǔ)言,這樣做的優(yōu)點(diǎn)是,你能夠不必用復(fù)雜的方法去解決本來(lái)非常easy的問題。比如,你能夠用一個(gè)命令行解決簡(jiǎn)單的問題,而C不行,即使一個(gè)再簡(jiǎn)單的程序,C語(yǔ)言也必須經(jīng)過編寫、編譯的全過程。其次。awk本身是解釋運(yùn)行的,這就使得awk程序不必經(jīng)過編譯的過程,同一時(shí)候,這也使得它與shellscript程序能夠非常好的契合。
最后,awk本身較C語(yǔ)言簡(jiǎn)單,盡管awk吸收了C語(yǔ)言非常多優(yōu)秀的成分。熟悉C語(yǔ)言會(huì)對(duì)學(xué)習(xí)awk有非常大的幫助。但awk本身不須要會(huì)使用C語(yǔ)言——一種功能強(qiáng)大但須要大量時(shí)間學(xué)習(xí)才干掌握其技巧的開發(fā)工具。
使用awk的第三個(gè)理由是awk是一個(gè)easy獲得的工具。與C和C++語(yǔ)言不同,awk僅僅有一個(gè)文件(/bin/awk),并且差點(diǎn)兒每一個(gè)版本號(hào)的UNIX都提供各自版本號(hào)的awk,你全然不必費(fèi)心去想怎樣獲得awk。但C語(yǔ)言卻不是這樣。盡管C語(yǔ)言是UNIX天然的開發(fā)工具,但這個(gè)開發(fā)工具卻是單獨(dú)發(fā)行的。換言之。你必須為你的UNIX版本號(hào)的C語(yǔ)言開發(fā)工具單獨(dú)付費(fèi)(當(dāng)然使用D版者除外),獲得并安裝它,然后你才干夠使用它。
基于以上理由。再加上awk強(qiáng)大的功能,我們有理由說(shuō),假設(shè)你要處理與文本樣式掃描相關(guān)的工作,awk應(yīng)該是你的第一選擇。在這里有一個(gè)可遵循的一般原則:假設(shè)你用普通的shell工具或shellscript有困難的話,試試awk,假設(shè)awk仍不能解決這個(gè)問題。則便用C語(yǔ)言,假設(shè)C語(yǔ)言仍然失敗,則移至C++。
1awk的調(diào)用方式
前面以前說(shuō)過。awk提供了適應(yīng)多種須要的不同解決方式。它們是:
1)awk命令行。
你能夠象使用普通UNIX命令一樣使用awk,在命令行中你也能夠使用awk程序設(shè)計(jì)語(yǔ)言,盡管awk支持多行的錄入。可是錄入長(zhǎng)長(zhǎng)的命令行并保證其正確無(wú)誤卻是一件令人頭疼的事。因此。這樣的方法一般僅僅用于解決簡(jiǎn)單的問題。當(dāng)然,你也能夠在shellscript程序中引用awk命令行甚至awk程序腳本。
2)使用-f選項(xiàng)調(diào)用awk程序。awk同意將一段awk程序?qū)懭胍粋€(gè)文本文件。然后在awk命令行中用-f選項(xiàng)調(diào)用并運(yùn)行這段程序。詳細(xì)的方法我們將在后面的awk語(yǔ)法中講到。
3)利用命令解釋器調(diào)用awk程序。利用UNIX支持的命令解釋器功能。我們能夠?qū)⒁欢?span style="font-family:'Times New Roman', serif;">awk程序?qū)懭胛谋疚募?#xff0c;然后在它的第一行加上:
#!/bin/awk-f
并賦予這個(gè)文本文件以運(yùn)行的權(quán)限。這樣做之后。你就能夠在命令行中用類似于以下這種方式調(diào)用并運(yùn)行這段awk程序了。
$awk腳本文本名待處理文件
2awk的語(yǔ)法
與其他UNIX命令一樣,awk擁有自己的語(yǔ)法:
awk[ -F re] [parameter...] ['prog'] [-f progfile][in_file...]
參數(shù)說(shuō)明:
1)-Fre:同意awk更改其字段分隔符。
2)parameter: 該參數(shù)幫助為不同的變量賦值。
3)'prog':awk的程序語(yǔ)句段。這個(gè)語(yǔ)句段必須用單引號(hào):'和'括起。以防被shell解釋。
這個(gè)程序語(yǔ)句段的標(biāo)準(zhǔn)形式為:
'pattern{action}'
當(dāng)中pattern參數(shù)能夠是egrep正則表達(dá)式中的不論什么一個(gè),它能夠使用語(yǔ)法/re/再加上一些樣式匹配技巧構(gòu)成。與sed類似。你也能夠使用","分開兩樣式以選擇某個(gè)范圍。關(guān)于匹配的細(xì)節(jié)。你能夠參考附錄。假設(shè)仍不懂的話。找本UNIX書學(xué)學(xué)grep和sed(本人是在學(xué)習(xí)sed時(shí)掌握匹配技術(shù)的)。
action參數(shù)總是被大括號(hào)包圍,它由一系統(tǒng)awk語(yǔ)句組成,各語(yǔ)句之間用";"分隔。awk解釋它們,并在pattern給定的樣式匹配的記錄上運(yùn)行其操作。與shell類似,你也能夠使用“#”作為凝視符,它使“#”到行尾的內(nèi)容成為凝視,在解釋運(yùn)行時(shí),它們將被忽略。
你能夠省略pattern和action之中的一個(gè)。但不能兩者同一時(shí)候省略,當(dāng)省略pattern時(shí)沒有樣式匹配,表示對(duì)全部行(記錄)均運(yùn)行操作。省略action時(shí)運(yùn)行缺省的操作——在標(biāo)準(zhǔn)輸出上顯示。
4)-f progfile:同意awk調(diào)用并運(yùn)行progfile指定的程序文件。progfile是一個(gè)文本文件,他必須符合awk的語(yǔ)法。
5)in_file:awk的輸入文件。awk同意對(duì)多個(gè)輸入文件進(jìn)行處理。值得注意的是awk不改動(dòng)輸入文件。假設(shè)未指定輸入文件。awk將接受標(biāo)準(zhǔn)輸入。并將結(jié)果顯示在標(biāo)準(zhǔn)輸出上。awk支持輸入輸出重定向。
3awk的記錄、字段與內(nèi)置變量
前面說(shuō)過,awk處理的工作與數(shù)據(jù)庫(kù)的處理方式有同樣之處,其同樣處之中的一個(gè)就是awk支持對(duì)記錄和字段的處理。當(dāng)中對(duì)字段的處理是grep和sed不能實(shí)現(xiàn)的,這也是awk優(yōu)于二者的原因之中的一個(gè)。在awk中,缺省的情況下總是將文本文件里的一行視為一個(gè)記錄,而將一行中的某一部分作為記錄中的一個(gè)字段。
為了操作這些不同的字段,awk借用shell的方法,用$1,$2,$3...這種方式來(lái)順序地表示行(記錄)中的不同字段。
特殊地,awk用$0表示整個(gè)行(記錄)。不同的字段之間是用稱作分隔符的字符分隔開的。
系統(tǒng)默認(rèn)的分隔符是空格。awk同意在命令行中用-Fre的形式來(lái)改變這個(gè)分隔符。其實(shí),awk用一個(gè)內(nèi)置的變量FS來(lái)記憶這個(gè)分隔符。
awk中有好幾個(gè)這種內(nèi)置變量。比如,記錄分隔符變量RS、當(dāng)前工作的記錄數(shù)NR等等。本文后面的附表列出了所有的內(nèi)置變量。這些內(nèi)置的變量能夠在awk程序中引用或改動(dòng),比如,你能夠利用NR變量在模式匹配中指定工作范圍,也能夠通過改動(dòng)記錄分隔符RS讓一個(gè)特殊字符而不是換行符作為記錄的分隔符。
例:顯示文本文件myfile中第七行到第十五行中以字符%分隔的第一字段,第三字段和第七字段:
$awk -F % 'NR==7,NR==15{printf $1 $3 $7}' myfile
4awk的內(nèi)置函數(shù)
awk之所以成為一種優(yōu)秀的程序設(shè)計(jì)語(yǔ)言的原因之中的一個(gè)是它吸收了某些優(yōu)秀的程序設(shè)計(jì)語(yǔ)言(比如C)語(yǔ)言的很多長(zhǎng)處。這些長(zhǎng)處之中的一個(gè)就是內(nèi)置函數(shù)的使用,awk定義并支持了一系列的內(nèi)置函數(shù)。因?yàn)檫@些函數(shù)的使用,使得awk提供的功能更為完好和強(qiáng)大,比如,awk使用了一系列的字符串處理內(nèi)置函數(shù)(這些函數(shù)看起來(lái)與C語(yǔ)言的字符串處理函數(shù)相似,其使用方式與C語(yǔ)言中的函數(shù)也相差無(wú)幾)。正是因?yàn)檫@些內(nèi)置函數(shù)的使用,使awk處理字符串的功能更加強(qiáng)大。本文后面的附錄中列有一般的awk所提供的內(nèi)置函數(shù),這些內(nèi)置函數(shù)或許與你的awk版本號(hào)有些出入,因此。在使用之前,最好參考一下你的系統(tǒng)中的聯(lián)機(jī)幫助。
作為內(nèi)置函數(shù)的一個(gè)樣例,我們將在這里介紹awk的printf函數(shù),這個(gè)函數(shù)使得awk與c語(yǔ)言的輸出相一致。實(shí)際上。awk中有很多引用形式都是從C語(yǔ)言借用過來(lái)的。假設(shè)你熟悉C語(yǔ)言。你或許會(huì)記得當(dāng)中的printf函數(shù),它提供的強(qiáng)大格式輸出功能以前帶我們很多的方便。
幸運(yùn)的是,我們?cè)?span style="font-family:'Times New Roman', serif;">awk中又和它重逢了。awk中printf差點(diǎn)兒與C語(yǔ)言中一模一樣,假設(shè)你熟悉C語(yǔ)言的話,你全然能夠照C語(yǔ)言的模式使用awk中的printf。因此在這里。我們僅僅給出一個(gè)樣例,假設(shè)你不熟悉的話。請(qǐng)隨便找一本C語(yǔ)言的入門書翻翻。
例:顯示文件myfile中的行號(hào)和第3字段:
$awk'{printf"%03d%s\n",NR,$1}' myfile
5在命令行使用awk
依照順序,我們應(yīng)當(dāng)解說(shuō)awk程序設(shè)計(jì)的內(nèi)容了,但在解說(shuō)之前,我們將用一些樣例來(lái)對(duì)前面的知識(shí)進(jìn)行回想,這些樣例都是在命令行中使用的,由此我們能夠知道在命令行中使用awk是多么的方便。這樣做的原因一方面是為以下的內(nèi)容作鋪墊,還有一方面是介紹一些解決簡(jiǎn)單問題的方法。我們?nèi)粵]有必要用復(fù)雜的方法來(lái)解決簡(jiǎn)單的問題----既然awk提供了較為簡(jiǎn)單的方法的話。
例:顯示文本文件mydoc匹配(含有)字符串"sun"的全部行。
$awk'/sun/{print}' mydoc
因?yàn)轱@示整個(gè)記錄(全行)是awk的缺省動(dòng)作,因此能夠省略action項(xiàng)。
$awk'/sun/' mydoc
例:以下是一個(gè)較為復(fù)雜的匹配的演示樣例:
$awk'/[Ss]un/, /[Mm]oon/{print}'myfile
它將顯示第一個(gè)匹配Sun或sun的行與第一個(gè)匹配Moon或moon的行之間的行(注意:!
。),并顯示到標(biāo)準(zhǔn)輸出上。
例:以下的演示樣例顯示了內(nèi)置變量和內(nèi)置函數(shù)length()的使用:
$awk'length($0)>80{print NR}' myfile
該命令行將顯示文本myfile中全部超過80個(gè)字符的行號(hào)。在這里,用$0表示整個(gè)記錄(行),同一時(shí)候,內(nèi)置變量NR不使用標(biāo)志符'$'。
例:作為一個(gè)較為實(shí)際的樣例。我們?nèi)绻獙?duì)UNIX中的用戶進(jìn)行安全性檢查。方法是考察/etc下的passwd文件,檢查當(dāng)中的passwd字段(第二字段)是否為"*",如不為"*"。則表示該用戶沒有設(shè)置password,顯示出這些username(第一字段)。我們能夠用例如以下語(yǔ)句實(shí)現(xiàn):
#awk-F: '$2==""{printf("%s no password!\n",$1}'/etc/passwd
在這個(gè)演示樣例中。passwd文件的字段分隔符是“:”。因此。必須用-F:來(lái)更改默認(rèn)的字段分隔符。這個(gè)演示樣例中也涉及到了內(nèi)置函數(shù)printf的使用。
6awk的變量
如同其他程序設(shè)計(jì)語(yǔ)言一樣,awk同意在程序語(yǔ)言中設(shè)置變量。其實(shí),提供變量的功能是程序設(shè)計(jì)語(yǔ)言的其本要求。不提供變量的程序設(shè)計(jì)語(yǔ)言本人還從未見過。
awk提供兩種變量,一種是內(nèi)置變量。這前面我們已經(jīng)講過,須要著重指出的是,與后面提到的其他變量不同的是。在awk程序中引用內(nèi)置變量不須要使用標(biāo)志符"$"(回顧一下前面講過的NR的使用)。awk提供的還有一種變量是自己定義變量。awk同意用戶在awk程序語(yǔ)句中定義并調(diào)用自已的變量。
當(dāng)然這樣的變量不能與內(nèi)置變量及其他awk保留字同樣。在awk中引用自己定義變量必須在它前面加上標(biāo)志符"$"。
與C語(yǔ)言不同的是,awk中不須要對(duì)變量進(jìn)行初始化,awk依據(jù)其在awk中第一次出現(xiàn)的形式和上下文確定其詳細(xì)的數(shù)據(jù)類型。當(dāng)變量類型不確定時(shí)。awk默認(rèn)其為字符串類型。
這里有一個(gè)技巧:假設(shè)你要讓你的awk程序知道你所使用的變量的明白類型,你應(yīng)當(dāng)在在程序中給它賦初值。在后面的實(shí)例中。我們將用到這一技巧。
7運(yùn)算與推斷
作為一種程序設(shè)計(jì)語(yǔ)言所應(yīng)具有的特點(diǎn)之中的一個(gè)。awk支持多種運(yùn)算,這些運(yùn)算與C語(yǔ)言提供的基本同樣:如+、-、*、/、%等等,同一時(shí)候。awk也支持C語(yǔ)言中類似++、--、+=、-=、=+、=-之類的功能,這給熟悉C語(yǔ)言的使用者編寫awk程序帶來(lái)了極大的方便。作為對(duì)運(yùn)算功能的一種擴(kuò)展,awk還提供了一系列內(nèi)置的運(yùn)算函數(shù)(如log、sqr、cos、sin等等)和一些用于對(duì)字符串進(jìn)行操作(運(yùn)算)的函數(shù)(如length、substr等等)。這些函數(shù)的引用大大的提高了awk的運(yùn)算功能。
作為對(duì)條件轉(zhuǎn)移指令的一部分,關(guān)系推斷是每種程序設(shè)計(jì)語(yǔ)言都具備的功能,awk也不例外。awk中同意進(jìn)行多種測(cè)試,如經(jīng)常使用的==(等于)、!=(不等于)、>(大于)、<(小于)、>=(大于等于)、>=(小于等于)等等。同一時(shí)候,作為樣式匹配,還提供了~(匹配于)和!
~(不匹配于)推斷。
作為對(duì)測(cè)試的一種擴(kuò)充,awk也支持用邏輯運(yùn)算符:!(非)、&&(與)、||(或)和括號(hào)()進(jìn)行多重推斷。這大大增強(qiáng)了awk的功能。本文的附錄中列出了awk所同意的運(yùn)算、推斷以及操作符的優(yōu)先級(jí)。
8awk的流程控制
流程控制語(yǔ)句是不論什么程序設(shè)計(jì)語(yǔ)言都不能缺少的部分。不論什么好的語(yǔ)言都有一些運(yùn)行流程控制的語(yǔ)句。awk提供的完備的流程控制語(yǔ)句類似于C語(yǔ)言。這給我們編程帶來(lái)了極大的方便。
8.1BEGIN和END:
在awk中兩個(gè)特別的表達(dá)式。BEGIN和END,這兩者都可用于pattern中(參考前面的awk語(yǔ)法),提供BEGIN和END的作用是給程序賦予初始狀態(tài)和在程序結(jié)束之后運(yùn)行一些掃尾的工作。不論什么在BEGIN之后列出的操作(在{}內(nèi))將在awk開始掃描輸入之前運(yùn)行,而END之后列出的操作將在掃描完所有的輸入之后運(yùn)行。因此。通常使用BEGIN來(lái)顯示變量和預(yù)置(初始化)變量。使用END來(lái)輸出終于結(jié)果。
例:累計(jì)銷售文件xs中的銷售金額(如果銷售金額在記錄的第三字段):
$awk
>'BEGIN{ FS=":";print "統(tǒng)計(jì)銷售金額";total=0}
>{print$3;total=total+$3;}
>END{printf "銷售金額總計(jì):%.2f",total}'sx
(注:>是shell提供的第二提示符。如要在shell程序awk語(yǔ)句和awk語(yǔ)言中換行,則需在行尾加反斜杠\)
在這里,BEGIN預(yù)置了內(nèi)部變量FS(字段分隔符)和自己定義變量total,同一時(shí)候在掃描之前顯示出輸出行頭。而END則在掃描完畢后打印出總合計(jì)。
8.2流程控制語(yǔ)句
awk提供了完備的流程控制語(yǔ)句,其使用方法與C語(yǔ)言類似。以下我們一一加以說(shuō)明:
8.2.1if...else語(yǔ)句:
格式:
if(表達(dá)式)
語(yǔ)句1
else
語(yǔ)句2
格式中"語(yǔ)句1"能夠是多個(gè)語(yǔ)句,假設(shè)你為了方便awk推斷也方便你自已閱讀。你最好將多個(gè)語(yǔ)句用{}括起來(lái)。
awk分枝結(jié)構(gòu)同意嵌套,其格式為:
if(表達(dá)式1)
{if(表達(dá)式2)
語(yǔ)句1
else
語(yǔ)句2
}
語(yǔ)句3
else{if(表達(dá)式3)
語(yǔ)句4
else
語(yǔ)句5
}
語(yǔ)句6
當(dāng)然實(shí)際操作過程中你可能不會(huì)用到如此復(fù)雜的分枝結(jié)構(gòu),這里僅僅是為了給出其樣式罷了。
8.2.2while語(yǔ)句
格式為:
while(表達(dá)式)
語(yǔ)句
8.2.3do-while語(yǔ)句
格式為:
do
{
語(yǔ)句
}while(條件推斷語(yǔ)句)
8.2.4for語(yǔ)句
格式為:
for(初始表達(dá)式;終止條件;步長(zhǎng)表達(dá)式)
{語(yǔ)句}
在awk的while、do-while和for語(yǔ)句中同意使用break,continue語(yǔ)句來(lái)控制流程走向。也同意使用exit這種語(yǔ)句來(lái)退出。break中斷當(dāng)前正在運(yùn)行的循環(huán)并跳到循環(huán)外運(yùn)行下一條語(yǔ)句。continue從當(dāng)前位置跳到循環(huán)開始處運(yùn)行。對(duì)于exit的運(yùn)行有兩種情況:當(dāng)exit語(yǔ)句不在END中時(shí),不論什么操作中的exit命令表現(xiàn)得如同到了文件尾,全部模式或操作運(yùn)行將停止。END模式中的操作被運(yùn)行。而出如今END中的exit將導(dǎo)致程序終止。
9awk中的自己定義函數(shù)
定義和調(diào)用用戶自己的函數(shù)是差點(diǎn)兒每一個(gè)高級(jí)語(yǔ)言都具有的功能,awk也不例外,但原始的awk并不提供函數(shù)功能,僅僅有在nawk或較新的awk版本號(hào)中才干夠添加函數(shù)。
函數(shù)的使用包括兩部分:函數(shù)的定義與函數(shù)調(diào)用。
當(dāng)中函數(shù)定義又包括要運(yùn)行的代碼(函數(shù)本身)和從主程序代碼傳遞到該函數(shù)的暫時(shí)調(diào)用。
awk函數(shù)的定義方法例如以下:
function函數(shù)名(參數(shù)表){
函數(shù)體
}
在gawk中同意將function省略為func,但其他版本號(hào)的awk不同意。函數(shù)名必須是一個(gè)合法的標(biāo)志符,參數(shù)表中能夠不提供參數(shù)(但在調(diào)用函數(shù)時(shí)函數(shù)名后的一對(duì)括號(hào)仍然是必不可少的)。也能夠提供一個(gè)或多個(gè)參數(shù)。與C語(yǔ)言相似。awk的參數(shù)也是通過值來(lái)傳遞的。
在awk中調(diào)用函數(shù)比較簡(jiǎn)單,其方法與C語(yǔ)言相似,但awk比C語(yǔ)言更為靈活,它不運(yùn)行參數(shù)有效性檢查。換句話說(shuō)。在你調(diào)用函數(shù)時(shí),能夠列出比函數(shù)估計(jì)(函數(shù)定義中規(guī)定)的多或少的參數(shù),多余的參數(shù)會(huì)被awk所忽略。而不足的參數(shù),awk將它們置為缺省值0或空字符串,詳細(xì)置為何值。將取決于參數(shù)的使用方式。
awk函數(shù)有兩種返回方式:隱式返回和顯式返回。當(dāng)awk運(yùn)行到函數(shù)的結(jié)尾時(shí)。它自己主動(dòng)地返回到調(diào)用程序,這是函數(shù)是隱式返回的。假設(shè)須要在結(jié)束之前退出函數(shù),能夠明白地使用返回語(yǔ)句提前退出。方法是在函數(shù)中使用形如:return返回值格式的語(yǔ)句。
例:以下的樣例演示了函數(shù)的使用。在這個(gè)演示樣例中,定義了一個(gè)名為print_header的函數(shù),該函數(shù)調(diào)用了兩個(gè)參數(shù)FileName和PageNum,FileName參數(shù)傳給函數(shù)當(dāng)前使用的文件名稱,PageNum參數(shù)是當(dāng)前頁(yè)的頁(yè)號(hào)。
這個(gè)函數(shù)的功能是打印(顯示)出當(dāng)前文件的文件名稱,和當(dāng)前頁(yè)的頁(yè)號(hào)。完畢這個(gè)功能后。這個(gè)函數(shù)將返回下一頁(yè)的頁(yè)號(hào)。
nawk
>'BEGIN{pageno=1;file=FILENAME
>pageno=print_header(file。pageno);#調(diào)用函數(shù)print_header
>printf("當(dāng)前頁(yè)頁(yè)號(hào)是:%d\n",pageno);
>}
>#定義函數(shù)print_header
>functionprint_header(FileName,PageNum){
>printf("%s%d\n",FileName,PageNum);
>PageNum++;
>returnPageNUm;
>}
>}' myfile
運(yùn)行這個(gè)程序?qū)@演示樣例如以下內(nèi)容:
myfile1
當(dāng)前頁(yè)頁(yè)號(hào)是:2
10awk高級(jí)輸入輸出
10.1讀取下一條記錄:
awk的next語(yǔ)句導(dǎo)致awk讀取下一個(gè)記錄并完畢模式匹配。然后馬上運(yùn)行對(duì)應(yīng)的操作。通常它用匹配的模式運(yùn)行操作中的代碼。next導(dǎo)致這個(gè)記錄的不論什么額外匹配模式被忽略。
10.2簡(jiǎn)單地讀取一條記錄
awk的getline語(yǔ)句用于簡(jiǎn)單地讀取一條記錄。假設(shè)用戶有一個(gè)數(shù)據(jù)記錄類似兩個(gè)物理記錄,那么getline將尤事實(shí)上用。它完畢一般字段的分離(設(shè)置字段變量$0FNR NFNR)。假設(shè)成功則返回1。失敗則返回0(到達(dá)文件尾)。假設(shè)需簡(jiǎn)單地讀取一個(gè)文件,則能夠編寫下面代碼:
例:演示樣例getline的使用
{while(getline==1)
{
#processthe inputted fields
}
}
也能夠使getline保存輸入數(shù)據(jù)在一個(gè)字段中,而不是通過使用getlinevariable的形式處理一般字段。當(dāng)使用這樣的方式時(shí),NF被置成0,FNR和NR被增值。
用戶也能夠使用getline<"filename"方式從一個(gè)給定的文件里輸入數(shù)據(jù),而不是從命令行所列內(nèi)容輸入數(shù)據(jù)。此時(shí)。getline將完畢一般字段分離(設(shè)置字段變量$0和NF)。假設(shè)文件不存在。返回-1,成功,返回1,返回0表示失敗。用戶能夠從給定文件里讀取數(shù)據(jù)到一個(gè)變量中,也能夠用stdin(標(biāo)準(zhǔn)輸入設(shè)備)或一個(gè)包括這個(gè)文件名稱的變量取代filename。值得注意的是當(dāng)使用這樣的方式時(shí)不改動(dòng)FNR和NR。
還有一種使用getline語(yǔ)句的方法是從UNIX命令接受輸入,比如以下的樣例:
例:演示樣例從UNIX命令接受輸入
{while("who-u"|getline)
{
#process each line fromthe who command
}
}
當(dāng)然,也能夠使用例如以下形式:
"command"| getline variable
10.3關(guān)閉文件:
awk中同意在程序中關(guān)閉一個(gè)輸入或輸出文件。方法是使用awk的close語(yǔ)句。
close("filename")
filename能夠是getline打開的文件(也能夠是stdin,包括文件名稱的變量或者getline使用的確切命令)。
或一個(gè)輸出文件(能夠是stdout。包括文件名稱的變量或使用管道的確切命令)。
10.4輸出到一個(gè)文件:
awk中同意用例如以下方式將結(jié)果輸出到一個(gè)文件:
printf("helloword!\n")>"datafile"
或
printf("helloword!\n")>>"datafile"
10.5輸出到一個(gè)命令
awk中同意用例如以下方式將結(jié)果輸出到一個(gè)命令:
printf("helloword!\n")|"sort-t','"
10awk與shellscript混合編程
由于awk能夠作為一個(gè)shell命令使用,因此awk能與shell批處理程序非常好的融合在一起,這給實(shí)現(xiàn)awk與shell程序的混合編程提供了可能。
實(shí)現(xiàn)混合編程的關(guān)鍵是awk與shellscript之間的對(duì)話。換言之,就是awk與shellscript之間的信息交流:awk從shellscript中獲取所需的信息(一般是變量的值)、在awk中運(yùn)行shell命令行、shellscript將命令運(yùn)行的結(jié)果送給awk處理以及shellscript讀取awk的運(yùn)行結(jié)果等等。
10.1awk讀取Shellscript程序變量
在awk中我們能夠通過“'$變量名'”的方式讀取shellscrpit程序中的變量。
例:在以下的演示樣例中,我們將讀取sellscrpit程序中的變量Name,該變量存放的是文本myfile的撰寫者,awk將打印出這個(gè)人名。
$catwritename
# !/bin/sh
Name="張三"
awk'BEGIN {name="'$Name'";\
printf("\t%s\t撰寫者%s\n",FILENAME,name");}\
{...}END{...}' myfile
10.2將shell命令的運(yùn)行結(jié)果送給awk處理
作為信息傳送的一種方法。我們能夠?qū)⒁粭lshell命令的結(jié)果通過管道線(|)傳遞給awk處理:
例:演示樣例awk處理shell命令的運(yùn)行結(jié)果
$who-u | awk '{printf("%s正在運(yùn)行%s\n",$2,$1)}'
該命令將打印出注冊(cè)終端正在運(yùn)行的程序名。
10.3shell script程序讀awk的運(yùn)行結(jié)果
為了實(shí)現(xiàn)shellscript程序讀取awk運(yùn)行的結(jié)果,我們能夠採(cǎi)取一些特殊的方法,比如我們能夠用變量名=`awk語(yǔ)句`的形式將awk運(yùn)行的結(jié)果存放入一個(gè)shellscript變量。當(dāng)然也能夠用管道線的方法將awk運(yùn)行結(jié)果傳遞給shellscript程序處理。
例:作為傳送消息的機(jī)制之中的一個(gè),UNIX提供了一個(gè)向其全部用戶傳送消息的命令wall(意思是writetoall寫給全部用戶),該命令同意向全部工作中的用戶(終端)發(fā)送消息。為此,我們能夠通過一段shell批處理程序wall.shell來(lái)模擬這一程序(其實(shí)比較老的版本號(hào)中wall就是一段shell批處理程序:
$catwall.shell
#!/bin/sh
who -u | awk '{print $2}' |while read tty
do
cat /tmp/$$>$tty #$$的作用是產(chǎn)生隨機(jī)的數(shù)字?
!!
done
在這個(gè)程序里。awk接受who-u命令的運(yùn)行結(jié)果,該命令打印出全部已注冊(cè)終端的信息,當(dāng)中第二個(gè)字段是已注冊(cè)終端的設(shè)備名,因此用awk命令析出該設(shè)備名。然后用whileread tty語(yǔ)句循環(huán)讀出這些文件名稱到變量(shellscript變量)tty中。作為信息傳送的終結(jié)地址。
10.4在awk中運(yùn)行shell命令行----嵌入函數(shù)system()
system()是一個(gè)不適合字符或數(shù)字類型的嵌入函數(shù),該函數(shù)的功能是處理作為參數(shù)傳遞給它的字符串。system對(duì)這個(gè)參數(shù)的處理就是將其作為命令處理,也就是說(shuō)將其當(dāng)作命令行一樣加以運(yùn)行。
這使得用戶在自己的awk程序須要時(shí)能夠靈活地運(yùn)行命令或腳本。
例:以下的程序?qū)⑹褂?span style="font-family:'Times New Roman', serif;">system嵌入函數(shù)打印用戶編制好的報(bào)表文件,這個(gè)文件存放在名為myreport.txt的文件里。為簡(jiǎn)約起見,我們僅僅列出了其END部分:
.
.
.
END{close("myreport.txt");system("lpmyreport.txt");}
在這個(gè)演示樣例中,我們首先使用close語(yǔ)句關(guān)閉了文件myreport.txt文件。然后使用system嵌入函數(shù)將myreport.txt送入打印機(jī)打印。
寫到這里,我不得不跟朋友們說(shuō)再見了,實(shí)在地說(shuō),這些內(nèi)容仍然是awk的初步知識(shí),電腦永遠(yuǎn)是前進(jìn)的科學(xué)。awk也不例外。本篇所能做的僅僅是在你前行的漫漫長(zhǎng)途中鋪平一段小小開端。剩下的路還得靠你自己去走。
老實(shí)說(shuō),假設(shè)本文真能給你前行的路上帶來(lái)些許的方便,那本人就知足了!
如對(duì)本篇有不論什么疑問,請(qǐng)E-mailTo:Chizlong@yeah.net或到主頁(yè)http://chizling.yeah.net中留言。
附錄
附1awk的常規(guī)表達(dá)式元字符
\換碼序列
^在字符串的開頭開始匹配
$在字符串的結(jié)尾開始匹配
.與不論什么單個(gè)字符串匹配
[ABC]與[]內(nèi)的任一字符匹配
[A-Ca-c]與A-C及a-c范圍內(nèi)的字符匹配(按字母表順序)
[^ABC]與除[]內(nèi)的全部字符以外的任一字符匹配
Desk|Chair與Desk和Chair中的任一個(gè)匹配
[ABC][DEF]關(guān)聯(lián)。與A、B、C中的任一字符匹配。且其后要跟D、E、F中的任一個(gè)字符。
*與A、B或C中任一個(gè)出現(xiàn)0次或多次的字符相匹配
+與A、B或C中不論什么一個(gè)出現(xiàn)1次或多次的字符相匹配
?與一個(gè)空串或A、B或C在不論什么一個(gè)字符相匹配
(Blue|Black)berry合并常規(guī)表達(dá)式,與Blueberry或Blackberry相匹配
附2awk算術(shù)運(yùn)算符
運(yùn)算符用途
------------------
x^yx的y次冪
x**y同上
x%y計(jì)算x/y的余數(shù)(求模)
x+yx加y
x-yx減y
x*yx乘y
x/yx除y
-y負(fù)y(y的開關(guān)符號(hào));也稱一目減
++yy加1后使用y(前置加)
y++使用y值后加1(后綴加)
--yy減1后使用y(前置減)
y--使用后y減1(后綴減)
x=y將y的值賦給x
x+=y將x+y的值賦給x
x-=y將x-y的值賦給x
x*=y將x*y的值賦給x
x/=y將x/y的值賦給xx%=y 將x%y的值賦給x
x^=y將x^y的值賦給x
x**=y將x**y的值賦給x
附3awk同意的測(cè)試
操作符含義
x==yx等于y
x!=yx不等于y
x>yx大于y
x>=yx大于或等于y
x<yx小于y
x<=yx小于或等于y?
x~rex匹配正則表達(dá)式re?
x!~rex不匹配正則表達(dá)式re?
附4awk的操作符(按優(yōu)先級(jí)升序排列)
=、+=、-=、*= 、/=、 %=
||
&&
>>= < <= == != ~ !~
xy (字符串連結(jié),'x''y'變成"xy")
+-
* / %
++ --
附5awk內(nèi)置變量(提前定義變量)
說(shuō)明:表中v項(xiàng)表示第一個(gè)支持變量的工具(下同):A=awk,N=nawk,P=POSIXawk,G=gawk
變量含義缺省值
--------------------------------------------------------
ARGC命令行參數(shù)個(gè)數(shù)
ARGIND當(dāng)前被處理文件的ARGV標(biāo)志符
ARGV命令行參數(shù)數(shù)組
CONVFMT數(shù)字轉(zhuǎn)換格式%.6g
ENVIRONUNIX環(huán)境變量
ERRNOUNIX系統(tǒng)錯(cuò)誤消息
FIELDWIDTHS輸入字段寬度的空白分隔字符串
FILENAME當(dāng)前輸入文件的名字
FNR當(dāng)前記錄數(shù)
FS輸入字段分隔符空格
IGNORECASE控制大寫和小寫敏感0(大寫和小寫敏感)
NF當(dāng)前記錄中的字段個(gè)數(shù)
NR已經(jīng)讀出的記錄數(shù)
OFMT數(shù)字的輸出格式%.6g
OFS輸出字段分隔符空格
ORS輸出的記錄分隔符新行
RS輸入的記錄他隔符新行
RSTART被匹配函數(shù)匹配的字符串首
RLENGTH被匹配函數(shù)匹配的字符串長(zhǎng)度
SUBSEP下標(biāo)分隔符"\034"
附6awk的內(nèi)置函數(shù)
函數(shù)用途或返回值
------------------------------------------------
gsub(reg,string,target)每次常規(guī)表達(dá)式reg匹配時(shí)替換target中的string
index(search,string)返回string中search串的位置
length(string)求串string中的字符個(gè)數(shù)
match(string,reg)返回常規(guī)表達(dá)式reg匹配的string中的位置
printf(format,variable)格式化輸出,按format提供的格式輸出變量variable。
split(string,store,delim)依據(jù)分界符delim,分解string為store的數(shù)組元素
sprintf(format,variable)返回一個(gè)包括基于format的格式化數(shù)據(jù)。variables是要放到串中的數(shù)據(jù)
strftime(format,timestamp)返回一個(gè)基于format的日期或者時(shí)間串。timestmp是systime()函數(shù)返回的時(shí)間
sub(reg,string,target)第一次當(dāng)常規(guī)表達(dá)式reg匹配,替換target串中的字符串
substr(string,position,len)返回一個(gè)以position開始len個(gè)字符的子串
tolower(string)返回string中相應(yīng)的小寫字符
toupper(string)返回string中相應(yīng)的大寫字符
atan(x,y)x的余切(弧度)
cos(x)x的余弦(弧度)
exp(x)e的x冪
int(x)x的整數(shù)部分
log(x)x的自然對(duì)數(shù)值
rand()0-1之間的隨機(jī)數(shù)
sin(x)x的正弦(弧度)
sqrt(x)x的平方根
srand(x)初始化隨機(jī)數(shù)發(fā)生器。假設(shè)忽略x,則使用system()
system()返回自1970年1月1日以來(lái)經(jīng)過的時(shí)間(按秒計(jì)算)
參考資料
1、《精通UNIX》(《UnderstandingUNIX》[美]StanKelly-Bootle 著李永峰等譯電子工業(yè)出版社)
2、《unix使用指南》(第2版)(UsingUNIX(SecondEdition)SteveMoritsugu等原著張擁軍、韓柯、原小玲等譯電子工業(yè)出版社出版、發(fā)行)
3、unix聯(lián)機(jī)手冊(cè):scoOpenSrever 5.05版.
4、感謝無(wú)名的網(wǎng)路資源提供者,因?yàn)槟銈冃燎诙鵁o(wú)私的勞動(dòng),INTERNET只是如此美妙!
版權(quán)聲明:本文博客原創(chuàng)文章。博客,未經(jīng)同意,不得轉(zhuǎn)載。
轉(zhuǎn)載于:https://www.cnblogs.com/mengfanrong/p/4757440.html
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的AWK增强的文本处理shell特征--AWK完全手册的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PAT (Basic Level) Pr
- 下一篇: (转)浅谈HTML5与css3画饼图!