awk基礎(chǔ)知識(shí)小結(jié)第2/2頁(yè)
10、循環(huán)結(jié)構(gòu)
循環(huán)結(jié)構(gòu)
awk 的 while 循環(huán)結(jié)構(gòu),它等同于相應(yīng)的 C 語(yǔ)言 while 循環(huán)。
awk 還有 "do...while" 循環(huán),它在代碼塊結(jié)尾處對(duì)條件求值,而不象標(biāo)準(zhǔn) while 循環(huán)那樣在開(kāi)始處求值。
它類似于其它語(yǔ)言中的 "repeat...until" 循環(huán)。
示例:
do...while 示例 {
count=1
do {
print "I get printed at least once no matter what"
} while ( count != 1 )
}
與一般的 while 循環(huán)不同,由于在代碼塊之后對(duì)條件求值,"do...while" 循環(huán)永遠(yuǎn)都至少執(zhí)行一次。
換句話說(shuō),當(dāng)?shù)谝淮斡龅狡胀?while 循環(huán)時(shí),如果條件為假,將永遠(yuǎn)不執(zhí)行該循環(huán)。
for 循環(huán)
awk 允許創(chuàng)建 for 循環(huán),它就象 while 循環(huán),也等同于 C 語(yǔ)言的 for 循環(huán):
for ( initial assignment; comparison; increment ) {
code block
}
示例:
for ( x = 1; x <= 4; x++ ) {
print "iteration",x
}
此段代碼將打?。?
iteration 1
iteration 2
iteration 3
iteration 4
break 和 continue
此外,如同 C 語(yǔ)言一樣,awk 提供了 break 和 continue 語(yǔ)句。使用這些語(yǔ)句可以更好地控制 awk 的循環(huán)結(jié)構(gòu)。以下是迫切需要 break 語(yǔ)句的代碼片斷:
while 死循環(huán)
while (1) {
print "forever and ever..."
}
因?yàn)?1 永遠(yuǎn)代表是真,這個(gè) while 循環(huán)將永遠(yuǎn)運(yùn)行下去。以下是一個(gè)只執(zhí)行十次的循環(huán):
break 語(yǔ)句示例 x=1
while(1) {
print "iteration",x
if ( x == 10 ) {
break
}
x++
}
這里,break 語(yǔ)句用于“逃出”最深層的循環(huán)。"break" 使循環(huán)立即終止,并繼續(xù)執(zhí)行循環(huán)代碼塊后面的語(yǔ)句。
continue 語(yǔ)句補(bǔ)充了 break,其作用如下:
x=1
while (1) {
if ( x == 4 ) {
x++
continue
}
print "iteration",x
if ( x > 20 ) {
break
}
x++
}
這段代碼打印 "iteration 1" 到 "iteration 21","iteration 4" 除外。如果迭代等于 4,則增加 x 并調(diào)用 continue 語(yǔ)句,該語(yǔ)句立即使 awk 開(kāi)始執(zhí)行下一個(gè)循環(huán)迭代,而不執(zhí)行代碼塊的其余部分。如同 break 一樣,continue 語(yǔ)句適合各種 awk 迭代循環(huán)。在 for 循環(huán)主體中使用時(shí),continue 將使循環(huán)控制變量自動(dòng)增加。以下是一個(gè)等價(jià)循環(huán):
for ( x=1; x<=21; x++ ) {
if ( x == 4 ) {
continue
}
print "iteration",x
}
在 while 循環(huán)中時(shí),在調(diào)用 continue 之前沒(méi)有必要增加 x,因?yàn)?for 循環(huán)會(huì)自動(dòng)增加 x。
數(shù)組
如果您知道 awk 可以使用數(shù)組,您一定會(huì)感到高興。然而,在 awk 中,數(shù)組下標(biāo)通常從 1 開(kāi)始,而不是 0:
myarray[1]="jim"
myarray[2]=456
awk 遇到第一個(gè)賦值語(yǔ)句時(shí),它將創(chuàng)建 myarray,并將元素 myarray[1] 設(shè)置成 "jim"。執(zhí)行了第二個(gè)賦值語(yǔ)句后,數(shù)組就有兩個(gè)元素了。
數(shù)組迭代
定義之后,awk 有一個(gè)便利的機(jī)制來(lái)迭代數(shù)組元素,如下所示:
for ( x in myarray ) {
print myarray[x]
}
這段代碼將打印數(shù)組 myarray 中的每一個(gè)元素。當(dāng)對(duì)于 for 使用這種特殊的 "in" 形式時(shí),awk 將 myarray 的每個(gè)現(xiàn)有下標(biāo)依次賦值給 x(循環(huán)控制變量),每次賦值以后都循環(huán)一次循環(huán)代碼。雖然這是一個(gè)非常方便的 awk 功能,但它有一個(gè)缺點(diǎn) -- 當(dāng) awk 在數(shù)組下標(biāo)之間輪轉(zhuǎn)時(shí),它不會(huì)依照任何特定的順序。那就意味著我們不能知道以上代碼的輸出是:
jim
456
還是:
456
jim
迭代數(shù)組內(nèi)容就像一盒巧克力-您永遠(yuǎn)不知道將會(huì)得到什么。
11、數(shù)組下標(biāo)字符串化
數(shù)組下標(biāo)字符串化
雖然 awk 要執(zhí)行必要的轉(zhuǎn)換來(lái)完成這項(xiàng)工作,但它卻可以使用某些看起來(lái)很奇怪的代碼:
a="1"
b="2"
c=a+b+3
執(zhí)行了這段代碼后,c 等于 6。由于 awk 是“字符串化”的,添加字符串 "1" 和 "2" 在功能上并不比添加數(shù)字 1 和 2 難。這兩種情況下,awk 都可以成功執(zhí)行運(yùn)算。awk 的“字符串化”性質(zhì)非??蓯?ài) -- 您可能想要知道如果使用數(shù)組的字符串下標(biāo)會(huì)發(fā)生什么情況。例如,以下代碼:
myarr["1"]="Mr. Whipple"
print myarr["1"]
可以預(yù)料,這段代碼將打印 "Mr. Whipple"。但如果去掉第二個(gè) "1" 下標(biāo)中的引號(hào),情況又會(huì)怎樣呢?
myarr["1"]="Mr. Whipple"
print myarr[1]
猜想這個(gè)代碼片斷的結(jié)果比較難。awk 將 myarr["1"] 和 myarr[1] 看作數(shù)組的兩個(gè)獨(dú)立元素,還是它們是指同一個(gè)元素?答案是它們指的是同一個(gè)元素,awk 將打印 "Mr. Whipple",如同第一個(gè)代碼片斷一樣。雖然看上去可能有點(diǎn)怪,但 awk 在幕后卻一直使用數(shù)組的字符串下標(biāo)!
了解了這個(gè)奇怪的真相之后,我們中的一些人可能想要執(zhí)行類似于以下的古怪代碼:
myarr["name"]="Mr. Whipple"
print myarr["name"]
這段代碼不僅不會(huì)產(chǎn)生錯(cuò)誤,而且它的功能與前面的示例完全相同,也將打印 "Mr. Whipple"!可以看到,awk 并沒(méi)有限制我們使用純整數(shù)下標(biāo);如果我們?cè)敢猓梢允褂米址聵?biāo),而且不會(huì)產(chǎn)生任何問(wèn)題。只要我們使用非整數(shù)數(shù)組下標(biāo),如 myarr["name"],那么我們就在使用關(guān)聯(lián)數(shù)組。從技術(shù)上講,如果我們使用字符串下標(biāo),awk 的后臺(tái)操作并沒(méi)有什么不同(因?yàn)榧幢闶褂谩罢麛?shù)”下標(biāo),awk 還是會(huì)將它看作是字符串)。但是,應(yīng)該將它們稱作關(guān)聯(lián)數(shù)組 -- 它聽(tīng)起來(lái)很酷,而且會(huì)給您的上司留下印象。字符串化下標(biāo)是我們的小秘密。;)
數(shù)組工具
談到數(shù)組時(shí),awk 給予我們?cè)S多靈活性。可以使用字符串下標(biāo),而且不需要連續(xù)的數(shù)字序列下標(biāo)(例如,可以定義 myarr[1] 和 myarr[1000],但不定義其它所有元素)。雖然這些都很有用,但在某些情況下,會(huì)產(chǎn)生混淆。幸好,awk 提供了一些實(shí)用功能有助于使數(shù)組變得更易于管理。
首先,可以刪除數(shù)組元素。如果想要?jiǎng)h除數(shù)組 fooarray 的元素 1,輸入:
delete fooarray[1]
而且,如果想要查看是否存在某個(gè)特定數(shù)組元素,可以使用特殊的 "in" 布爾運(yùn)算符,如下所示:
if ( 1 in fooarray ) {
print "Ayep! It's there."
} else {
print "Nope! Can't find it."
}
12、格式化輸出
awk 提供了兩個(gè)函數(shù)printf() 和 sprintf()。如同其它許多 awk 部件一樣,這些函數(shù)等同于相應(yīng)的 C 語(yǔ)言函數(shù)。
printf() 會(huì)將格式化字符串打印到 stdout,而 sprintf() 則返回可以賦值給變量的格式化字符串。
如果不熟悉 printf() 和 sprintf(),介紹 C 語(yǔ)言的文章可以讓您迅速了解這兩個(gè)基本打印函數(shù)。在 Linux 系統(tǒng)上,可以輸入 "man 3 printf" 來(lái)查看 printf() 幫助頁(yè)面。
以下是一些 awk sprintf() 和 printf() 的樣本代碼。可以看到,它們幾乎與 C 語(yǔ)言完全相同。
x=1
b="foo"
printf("%s got a %d on the last testn","Jim",83)
myout=("%s-%d",b,x)
print myout
此代碼將打印:
Jim got a 83 on the last test
foo-1
13、字符串函數(shù)
awk 有許多字符串函數(shù)。
在 awk 中,確實(shí)需要字符串函數(shù),因?yàn)椴荒芟笤谄渌Z(yǔ)言(如 C、C++ 和 Python)中那樣將字符串看作是字符數(shù)組。
例如,如果執(zhí)行以下代碼:
mystring="How are you doing today?"
print mystring[3]
將會(huì)接收到一個(gè)錯(cuò)誤,如下所示:
awk: string.gawk:59: fatal: attempt to use scalar as array
雖然不象 Python 的序列類型那樣方便,但 awk 的字符串函數(shù)還是可以完成任務(wù)。讓我們來(lái)看一下。
首先,有一個(gè)基本 length() 函數(shù),它返回字符串的長(zhǎng)度。以下是它的使用方法:
print length(mystring)
此代碼將打印值:
24
下一個(gè)字符串函數(shù)叫作 index,它將返回子字符串在另一個(gè)字符串中出現(xiàn)的位置,如果沒(méi)有找到該字符串則返回 0。使用 mystring,可以按以下方法調(diào)用它:
print index(mystring,"you")
awk 會(huì)打?。?BR>9
兩個(gè)簡(jiǎn)單的函數(shù),tolower() 和 toupper()。與您猜想的一樣,這兩個(gè)函數(shù)將返回字符串并且將所有字符分別轉(zhuǎn)換成小寫(xiě)或大寫(xiě)。請(qǐng)注意,tolower() 和 toupper() 返回新的字符串,不會(huì)修改原來(lái)的字符串。這段代碼:
print tolower(mystring)
print toupper(mystring)
print mystring
……
將產(chǎn)生以下輸出:
how are you doing today?
HOW ARE YOU DOING TODAY?
How are you doing today?
到現(xiàn)在為止一切不錯(cuò),但我們究竟如何從字符串中選擇子串,甚至單個(gè)字符?那就是使用 substr() 的原因。以下是 substr() 的調(diào)用方法:
mysub=substr(mystring,startpos,maxlen)
mystring 應(yīng)該是要從中抽取子串的字符串變量或文字字符串。startpos 應(yīng)該設(shè)置成起始字符位置,maxlen 應(yīng)該包含要抽取的字符串的最大長(zhǎng)度。請(qǐng)注意,我說(shuō)的是最大長(zhǎng)度;如果 length(mystring) 比 startpos+maxlen 短,那么得到的結(jié)果就會(huì)被截?cái)?。substr() 不會(huì)修改原始字符串,而是返回子串。以下是一個(gè)示例:
print substr(mystring,9,3)
awk 將打?。?BR>you
如果您通常用于編程的語(yǔ)言使用數(shù)組下標(biāo)訪問(wèn)部分字符串(以及不使用這種語(yǔ)言的人),請(qǐng)記住 substr() 是 awk 代替方法。
需要使用它來(lái)抽取單個(gè)字符和子串;因?yàn)?awk 是基于字符串的語(yǔ)言,所以會(huì)經(jīng)常用到它。
一些更耐人尋味的函數(shù)
首先是 match()。match() 與 index() 非常相似,它與 index() 的區(qū)別在于它并不搜索子串,它搜索的是規(guī)則表達(dá)式。match() 函數(shù)將返回匹配的起始位置,如果沒(méi)有找到匹配,則返回 0。此外,match() 還將設(shè)置兩個(gè)變量,叫作 RSTART 和 RLENGTH。RSTART 包含返回值(第一個(gè)匹配的位置),RLENGTH 指定它占據(jù)的字符跨度(如果沒(méi)有找到匹配,則返回 -1)。通過(guò)使用 RSTART、RLENGTH、substr() 和一個(gè)小循環(huán),可以輕松地迭代字符串中的每個(gè)匹配。以下是一個(gè) match() 調(diào)用示例:
print match(mystring,/you/), RSTART, RLENGTH
awk 將打印:
9 9 3
字符串替換
現(xiàn)在,我們將研究?jī)蓚€(gè)字符串替換函數(shù),sub() 和 gsub()。這些函數(shù)與目前已經(jīng)討論過(guò)的函數(shù)略有不同,因?yàn)樗鼈兇_實(shí)修改原始字符串。以下是一個(gè)模板,顯示了如何調(diào)用 sub():
sub(regexp,replstring,mystring)
調(diào)用 sub() 時(shí),它將在 mystring 中匹配 regexp 的第一個(gè)字符序列,并且用 replstring 替換該序列。sub() 和 gsub() 用相同的自變量;唯一的區(qū)別是 sub() 將替換第一個(gè) regexp 匹配(如果有的話),gsub() 將執(zhí)行全局替換,換出字符串中的所有匹配。以下是一個(gè) sub() 和 gsub() 調(diào)用示例:
sub(/o/,"O",mystring)
print mystring
mystring="How are you doing today?"
gsub(/o/,"O",mystring)
print mystring
必須將 mystring 復(fù)位成其初始值,因?yàn)榈谝粋€(gè) sub() 調(diào)用直接修改了 mystring。在執(zhí)行時(shí),此代碼將使 awk 輸出:
HOw are you doing today?
HOw are yOu dOing tOday?
當(dāng)然,也可以是更復(fù)雜的規(guī)則表達(dá)式。我把測(cè)試一些復(fù)雜規(guī)則表達(dá)式的任務(wù)留給您來(lái)完成。
通過(guò)介紹函數(shù) split(),我們來(lái)匯總一下已討論過(guò)的函數(shù)。split() 的任務(wù)是“切開(kāi)”字符串,并將各部分放到使用整數(shù)下標(biāo)的數(shù)組中。以下是一個(gè) split() 調(diào)用示例:
numelements=split("Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",mymonths,",")
調(diào)用 split() 時(shí),第一個(gè)自變量包含要切開(kāi)文字字符串或字符串變量。在第二個(gè)自變量中,應(yīng)該指定 split() 將填入片段部分的數(shù)組名稱。在第三個(gè)元素中,指定用于切開(kāi)字符串的分隔符。split() 返回時(shí),它將返回分割的字符串元素的數(shù)量。split() 將每一個(gè)片段賦值給下標(biāo)從 1 開(kāi)始的數(shù)組,因此以下代碼:
print mymonths[1],mymonths[numelements]
……將打?。?BR>Jan Dec
特殊字符串形式
簡(jiǎn)短注釋 -- 調(diào)用 length()、sub() 或 gsub() 時(shí),可以去掉最后一個(gè)自變量,這樣 awk 將對(duì) $0(整個(gè)當(dāng)前行)應(yīng)用函數(shù)調(diào)用。要打印文件中每一行的長(zhǎng)度,使用以下 awk 腳本:
{
print length()
}
相關(guān)文章
詳解Linux Shell 實(shí)現(xiàn)一個(gè)獲取任意位數(shù)的隨機(jī)密碼的腳本
這篇文章主要介紹了詳解Linux Shell 實(shí)現(xiàn)一個(gè)獲取任意位數(shù)的隨機(jī)密碼的腳本的相關(guān)資料,本文提供實(shí)現(xiàn)方法及實(shí)現(xiàn)代碼,需要的朋友可以參考下2017-08-08查看linux中某個(gè)端口(port)是否被占用的方法
下面小編就為大家?guī)?lái)一篇查看linux中某個(gè)端口(port)是否被占用的方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-05-05Linux crontab定時(shí)執(zhí)行Shell腳本需要執(zhí)行特定的命令時(shí)解決思路
今天小編就為大家分享一篇關(guān)于Linux crontab定時(shí)執(zhí)行Shell腳本需要執(zhí)行特定的命令時(shí)解決思路,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-01-01一文學(xué)會(huì)使用Linux內(nèi)核模塊&proc實(shí)例統(tǒng)計(jì)所有進(jìn)程信息
這篇文章主要介紹了使用Linux內(nèi)核模塊&proc實(shí)例統(tǒng)計(jì)所有進(jìn)程信息詳解,2023-05-05解決linux?shell中傳遞包含空格的參數(shù)問(wèn)題
這篇文章主要介紹了如何解決linux?shell中傳遞包含空格的參數(shù)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09PowerShell實(shí)現(xiàn)簡(jiǎn)單的grep功能
下面的PS腳本針對(duì)目錄和文件進(jìn)行了區(qū)分,借用Select-String命令,實(shí)現(xiàn)了內(nèi)容查找,并顯示查找到的文件和匹配內(nèi)容所在行號(hào)。感興趣的朋友一起看看吧2017-10-10