作者:cicc 2005-02-03 15:53:59 來(lái)自:Linux先生

          ??? a w k是一種程序語(yǔ)言,對(duì)文檔資料的處理具有很強(qiáng)的功能。awk 名稱是由它三個(gè)最初設(shè)計(jì)者的姓氏的第一個(gè)字母而命名的: Alfred V. Aho、Peter J. We i n b e rg e r、Brian W. Kernighan。
          ???a w k最初在1 9 7 7年完成。1 9 8 5年發(fā)表了一個(gè)新版本的a w k,它的功能比舊版本增強(qiáng)了不少。a w k能夠用很短的程序?qū)ξ臋n里的資料做修改、比較、提取、打印等處理。如果使用C 或P a s c a l等語(yǔ)言編寫(xiě)程序完成上述的任務(wù)會(huì)十分不方便而且很花費(fèi)時(shí)間,所寫(xiě)的程序也會(huì)很大。
          ???a w k不僅僅是一個(gè)編程語(yǔ)言,它還是L i n u x系統(tǒng)管理員和程序員的一個(gè)不可缺少的工具。a w k語(yǔ)言本身十分好學(xué),易于掌握,并且特別的靈活。
          ???gawk 是G N U計(jì)劃下所做的a w k,gawk 最初在1 9 8 6年完成,之后不斷地被改進(jìn)、更新。gawk 包含awk 的所有功能。

          6.1 gawk的主要功能

          ???gawk 的主要功能是針對(duì)文件的每一行( l i n e ),也就是每一條記錄,搜尋指定的格式。當(dāng)某一行符合指定的格式時(shí),gawk 就會(huì)在此行執(zhí)行被指定的動(dòng)作。gawk 依此方式自動(dòng)處理輸入文件的每一行直到輸入文件檔案結(jié)束。
          ???g a w k經(jīng)常用在如下的幾個(gè)方面:
          ???? 根據(jù)要求選擇文件的某幾行,幾列或部分字段以供顯示輸出。
          ???? 分析文檔中的某一個(gè)字出現(xiàn)的頻率、位置等。
          ???? 根據(jù)某一個(gè)文檔的信息準(zhǔn)備格式化輸出。
          ???? 以一個(gè)功能十分強(qiáng)大的方式過(guò)濾輸出文檔。
          ???? 根據(jù)文檔中的數(shù)值進(jìn)行計(jì)算。

          6.2 如何執(zhí)行g(shù)awk程序

          ???基本上有兩種方法可以執(zhí)行g(shù) a w k程序。
          ???如果gawk 程序很短,則可以將gawk 直接寫(xiě)在命令行,如下所示:
          ??????gawk 'program' input-file1 input-file2 ...
          ???
          ?? 其中program 包括一些pattern 和a c t i o n。
          ???如果gawk 程序較長(zhǎng),較為方便的做法是將gawk 程序存在一個(gè)文件中,gawk 的格式如下所示:
          ???gawk -f program-file input-file1 input-file2 ...
          ???gawk 程序的文件不止一個(gè)時(shí),執(zhí)行g(shù)awk 的格式如下所示:
          ???
          ???gawk -f program-file1 -f program-file2 ... input-file1 input-file2 ...

          6.3 文件、記錄和字段

          ???一般情況下,g a w k可以處理文件中的數(shù)值數(shù)據(jù),但也可以處理字符串信息。如果數(shù)據(jù)沒(méi)有存儲(chǔ)在文件中,可以通過(guò)管道命令和其他的重定向方法給g a w k提供輸入。當(dāng)然, g a w k只能處理文本文件(A S C I I碼文件)。?電話號(hào)碼本就是一個(gè)g a w k可以處理的文件的簡(jiǎn)單例子。電話號(hào)碼本由很多條目組成,每一個(gè)條目都有同樣的格式:姓、名、地址、電話號(hào)碼。每一個(gè)條目都是按字母順序排列。在g a w k中,每一個(gè)這樣的條目叫做一個(gè)記錄。它是一個(gè)完整的數(shù)據(jù)的集合。例如,電話號(hào)碼本中的Smith John這個(gè)條目,包括他的地址和電話號(hào)碼,就是一條記錄。
          ???記錄中的每一項(xiàng)叫做一個(gè)字段。在g a w k中,字段是最基本的單位。多個(gè)記錄的集合組成了一個(gè)文件。
          ???大多數(shù)情況下,字段之間由一個(gè)特殊的字符分開(kāi),像空格、TA B、分號(hào)等。這些字符叫做字段分隔符。請(qǐng)看下面這個(gè)/ e t c / p a s s w d文件:
          t p a r k e r ; t 3 6 s 6 2 h s h ; 5 0 1 ; 1 0 1 ; Tim Parker;/home/tparker;/bin/bash
          etreijs;2ys639dj3h;502;101;Ed Tr e i j s ; / h o m e / e t r e i j s ; / b i n / t c s h
          y c h o w ; 1 h 2 7 s j ; 5 0 3 ; 1 0 1 ; Yvonne Chow;/home/ychow;/bin/bash
          ???你可以看出/ e t c / p a s s w d文件使用分號(hào)作為字段分隔符。/ e t c / p a s s w d文件中的每一行都包括七個(gè)字段:用戶名;口令;用戶I D;工作組I D;注釋; h o m e目錄;啟始的外殼。如果你想要查找第六個(gè)字段,只需數(shù)過(guò)五個(gè)分號(hào)即可。
          ???但考慮到以下電話號(hào)碼本的例子,你就會(huì)發(fā)現(xiàn)一些問(wèn)題:
          Smith John 13 Wilson St. 555-1283
          Smith John 2736 Artside Dr Apt 123 555-2736
          Smith John 125 Westmount Cr 555-1726
          ???雖然我們能夠分辨出每個(gè)記錄包括四個(gè)字段,但g a w k卻無(wú)能為力。電話號(hào)碼本使用空格作為分隔符,所以g a w k認(rèn)為S m i t h是第一個(gè)字段, John 是第二個(gè)字段,1 3是第三個(gè)字段,依次類推。就g a w k而言,如果用空格作為字段分隔符的話,則第一個(gè)記錄有六個(gè)字段,而第二個(gè)記錄有八個(gè)字段。
          ???所以,我們必須找出一個(gè)更好的字段分隔符。例如,像下面一樣使用斜杠作為字段分隔符:
          Smith/John/13 Wilson St./555-1283
          Smith/John/2736 Artside Dr/Apt/123/555-2736
          Smith/John/125 Westmount Cr/555-1726
          ???如果你沒(méi)有指定其他的字符作為字段分隔符,那么g a w k將缺省地使用空格或TA B作為字段分隔符。

          6.4 模式和動(dòng)作

          ???在g a w k語(yǔ)言中每一個(gè)命令都由兩部分組成:一個(gè)模式( p a t t e r n)和一個(gè)相應(yīng)的動(dòng)作(a c t i o n)。只要模式符合,g a w k就會(huì)執(zhí)行相應(yīng)的動(dòng)作。其中模式部分用兩個(gè)斜杠括起來(lái),而動(dòng)作部分用一對(duì)花括號(hào)括起來(lái)。例如:
          / p a t t e r n 1 / { a c t i o n 1 }
          / p a t t e r n 2 / { a c t i o n 2 }
          / p a t t e r n 3 / { a c t i o n 3 }
          ???所有的g a w k程序都是由這樣的一對(duì)對(duì)的模式和動(dòng)作組成的。其中模式或動(dòng)作都能夠被省略,但是兩個(gè)不能同時(shí)被省略。如果模式被省略,則對(duì)于作為輸入的文件里面的每一行,動(dòng)作都會(huì)被執(zhí)行。如果動(dòng)作被省略,則缺省的動(dòng)作被執(zhí)行,既顯示出所有符合模式的輸入行而不做任何的改動(dòng)。
          ???下面是一個(gè)簡(jiǎn)單的例子,因?yàn)間awk 程序很短,所以將gawk 程序直接寫(xiě)在外殼命令行:
          gawk '/tparker/' /etc/passwd

          ????此程序在上面提到的/ e t c / p a s s w d文件中尋找符合t p a r k e r模式的記錄并顯示(此例中沒(méi)有動(dòng)作,所以缺省的動(dòng)作被執(zhí)行)。
          ???讓我們?cè)倏匆粋€(gè)例子:
          ???gawk '/UNIX/{print $2}' file2.data
          ???此命令將逐行查找f i l e 2 . d a t a文件中包含U N I X的記錄,并打印這些記錄的第二個(gè)字段。你也可以在一個(gè)命令中使用多個(gè)模式和動(dòng)作對(duì),例如:
          gawk '/scandal/{print $1} /rumor/{print $2}' gossip_file
          ???此命令搜索文件g o s s i p _ f i l e中包括s c a n d a l的記錄,并打印第一個(gè)字段。然后再?gòu)念^搜索g o s s i p _ f i l e中包括r u m o r的記錄,并打印第二個(gè)字段。

          6.5 比較運(yùn)算和數(shù)值運(yùn)算

          ???g a w k有很多比較運(yùn)算符,下面列出重要的幾個(gè):
          = = 相等
          ! = 不相等
          > 大于
          < 小于
          > = 大于等于
          < = 小于等于
          ???例如:??gawk '$4 > 100' testfile
          ???將會(huì)顯示文件testfile 中那些第四個(gè)字段大于1 0 0的記錄。
          ???下表列出了g a w k中基本的數(shù)值運(yùn)算符。
          ???運(yùn)算符說(shuō)明示例
          ???+ 加法運(yùn)算2+6
          ???- 減法運(yùn)算6-3
          ???* 乘法運(yùn)算2*5
          ???/ 除法運(yùn)算8/4
          ???^ 乘方運(yùn)算3^2 (=9)
          ???% 求余數(shù)9%4 (=1)
          ???例如:{print $3/2} 顯示第三個(gè)字段被2除的結(jié)果。
          ???在g a w k中,運(yùn)算符的優(yōu)先權(quán)和一般的數(shù)學(xué)運(yùn)算的優(yōu)先權(quán)一樣。例如:{print $1+$2*$3}
          ???顯示第二個(gè)字段和第三個(gè)字段相乘,然后和第一個(gè)字段相加的結(jié)果。
          ???你也可以用括號(hào)改變優(yōu)先次序。例如:
          ???{print ($1+$2)*$3}
          ???顯示第一個(gè)字段和第二個(gè)字段相加,然后和第三個(gè)字段相乘的結(jié)果。

          6.6 內(nèi)部函數(shù)

          g a w k中有各種的內(nèi)部函數(shù),現(xiàn)在介紹如下:?

          6.6.1 隨機(jī)數(shù)和數(shù)學(xué)函數(shù)

          sqrt(x) 求x 的平方根
          sin(x) 求x 的正弦函數(shù)
          cos(x) 求x 的余弦函數(shù)
          a t a n 2 ( x,y) 求x / y的余切函數(shù)
          log(x) 求x 的自然對(duì)數(shù)
          exp(x) 求x 的e 次方
          int(x) 求x 的整數(shù)部分
          rand() 求0 和1之間的隨機(jī)數(shù)
          srand(x) 將x 設(shè)置為r a n d ( )的種子數(shù)

          6.6.2 字符串的內(nèi)部函數(shù)

          ? i n d e x ( i n,find) 在字符串in 中尋找字符串find 第一次出現(xiàn)的地方,返回值是字符串find 出現(xiàn)在字符串in 里面的位置。如果在字符串in 里面找不到字符串f i n d,則返回值為0。
          例如:
          print index("peanut"," a n " )
          顯示結(jié)果3。
          ? length(string) 求出string 有幾個(gè)字符。
          例如:
          l e n g t h ( " a b c d e " )
          顯示結(jié)果5。
          ? m a t c h ( s t r i n g,r e g e x p ) 在字符串string 中尋找符合regexp 的最長(zhǎng)、最靠左邊的子字符串。返回值是regexp 在string 的開(kāi)始位置,即i n d e x值。match 函數(shù)將會(huì)設(shè)置系統(tǒng)變量R S TA RT 等于i n d e x的值,系統(tǒng)變量RLENGTH 等于符合的字符個(gè)數(shù)。如果不符合,則會(huì)設(shè)置R S TA RT 為0、RLENGTH 為- 1。
          ? s p r i n t f ( f o r m a t,e x p r e s s i o n 1,. . . ) 和printf 類似,但是sprintf 并不顯示,而是返回字符串。例如:
          sprintf("pi = %.2f (approx.)",2 2 / 7 )
          返回的字符串為pi = 3.14 (approx.)
          ? s u b ( r e g e x p,r e p l a c e m e n t,t a rg e t ) 在字符串t a rget 中尋找符合regexp 的最長(zhǎng)、最靠左的地方,以字串replacement 代替最左邊的r e g e x p。
          例如:
          str = "water,w a t e r,e v e r y w h e r e "
          s u b ( / a t /, " i t h ",s t r )
          結(jié)果字符串s t r會(huì)變成
          w i t h e r,w a t e r,e v e r y w h e r e
          ? g s u b ( r e g e x p,r e p l a c e m e n t,t a rget) 與前面的s u b類似。在字符串t a rget 中尋找符合r e g e x p的所有地方,以字符串replacement 代替所有的r e g e x p。例如:
          s t r = " w a t e r,w a t e r,e v e r y w h e r e "g s u b ( / a t /, " i t h ",s t r )
          結(jié)果字符串s t r會(huì)變成
          w i t h e r,w i t h e r,e v e r y w h e r e
          ? s u b s t r ( s t r i n g,s t a r t,length) 返回字符串string 的子字符串,這個(gè)子字符串的長(zhǎng)度為l e n g t h,從第start 個(gè)位置開(kāi)始。例如:
          s u b s t r ( " w a s h i n g t o n ",5,3 )返回值為i n g
          如果沒(méi)有l(wèi)ength ,則返回的子字符串是從第start 個(gè)位置開(kāi)始至結(jié)束。
          例如:
          s u b s t r ( " w a s h i n g t o n ",5 )
          返回值為i n g t o n。
          ? tolower(string) 將字符串s t r i n g的大寫(xiě)字母改為小寫(xiě)字母。
          例如:
          tolower("MiXeD cAsE 123")
          返回值為mixed case 123。
          ? toupper(string) 將字符串s t r i n g的小寫(xiě)字母改為大寫(xiě)字母。
          例如:
          toupper("MiXeD cAsE 123")
          返回值為MIXED CASE 123。

          6.6.3 輸入輸出的內(nèi)部函數(shù)

          ? close(filename) 將輸入或輸出的文件filename 關(guān)閉。
          ? system(command) 此函數(shù)允許用戶執(zhí)行操作系統(tǒng)的指令,執(zhí)行完畢后將回到g a w k程序。例如:
          BEGIN {system("ls")}

          6.7 字符串和數(shù)字

          字符串就是一連串的字符,它可以被g a w k逐字地翻譯。字符串用雙引號(hào)括起來(lái)。數(shù)字不能用雙引號(hào)括起來(lái),并且g a w k將它當(dāng)作一個(gè)數(shù)值。例如:
          gawk '$1 != "Tim" {print}' testfile
          此命令將顯示第一個(gè)字段和Ti m不相同的所有記錄。如果命令中Ti m兩邊不用雙引號(hào),g a w k將不能正確執(zhí)行。再如:
          gawk '$1 == "50" {print}' testfile
          ???此命令將顯示所有第一個(gè)字段和5 0這個(gè)字符串相同的記錄。g a w k不管第一字段中的數(shù)值的大小,而只是逐字地比較。這時(shí),字符串5 0和數(shù)值5 0并不相等。

          6.8 格式化輸出

          ???我們可以讓動(dòng)作顯示一些比較復(fù)雜的結(jié)果。例如:
          gawk '$1 != "Tim" {print $1,$ 5,$ 6,$2}' testfile
          將顯示t e s t f i l e文件中所有第一個(gè)字段和Ti m不相同的記錄的第一、第五、第六和第二個(gè)字段。進(jìn)一步,你可以在p r i n t動(dòng)作中加入字符串,例如:
          gawk '$1 != "Tim" {print "The entry for ",$ 1,"is not Tim. ",$2}' testfile
          ???p r i n t動(dòng)作的每一部分用逗號(hào)隔開(kāi)。
          ???借用C語(yǔ)言的格式化輸出指令,可以讓g a w k的輸出形式更為多樣。這時(shí),應(yīng)該用p r i n t f而不是p r i n t。例如:
          {printf "%5s likes this language\n",$ 2 }
          p r i n t f中的%5s 部分告訴gawk 如何格式化輸出字符串,也就是輸出5個(gè)字符長(zhǎng)。它的值由printf 的最后部分指出,在此是第二個(gè)字段。\ n是回車換行符。如果第二個(gè)字段中存儲(chǔ)的是人名,則輸出結(jié)果大致如下:
          Tim likes this language
          G e o ff likes this language
          Mike likes this language
          Joe likes this language
          ???gawk 語(yǔ)言支持的其他格式控制符號(hào)如下:
          ? c 如果是字符串,則顯示第一個(gè)字符;如果是整數(shù),則將數(shù)字以ASCII 字符的形式顯示。
          例如:
          printf “% c”,6 5
          結(jié)果將顯示字母A。
          ? d 顯示十進(jìn)制的整數(shù)。
          ? i 顯示十進(jìn)制的整數(shù)。
          ? e 將浮點(diǎn)數(shù)以科學(xué)記數(shù)法的形式顯示。
          例如:
          print “$ 4 . 3 e”,1 9 5 0
          結(jié)果將顯示1 . 9 5 0 e + 0 3。
          ? f 將數(shù)字以浮點(diǎn)的形式顯示。
          ? g 將數(shù)字以科學(xué)記數(shù)法的形式或浮點(diǎn)的形式顯示。數(shù)字的絕對(duì)值如果大于等于0 . 0 0 0 1則
          以浮點(diǎn)的形式顯示,否則以科學(xué)記數(shù)法的形式顯示。
          ? o 顯示無(wú)符號(hào)的八進(jìn)制整數(shù)。
          ? s 顯示一個(gè)字符串。
          ? x 顯示無(wú)符號(hào)的十六進(jìn)制整數(shù)。1 0至1 5以a至f表示。
          ? X 顯示無(wú)符號(hào)的十六進(jìn)制整數(shù)。1 0至1 5以A至F表示。
          ? % 它并不是真正的格式控制字符,% %將顯示%。
          當(dāng)你使用這些格式控制字符時(shí),你可以在控制字符前給出數(shù)字,以表示你將用的幾位或幾個(gè)字符。例如,6 d表示一個(gè)整數(shù)有6位。再請(qǐng)看下面的例子:
          {printf "%5s works for %5s and earns %2d an hour",$ 1,$ 2,$ 3 }
          將會(huì)產(chǎn)生類似如下的輸出:
          Joe works for Mike and earns 12 an hour
          當(dāng)處理數(shù)據(jù)時(shí),你可以指定數(shù)據(jù)的精確位數(shù)
          {printf "%5s earns $%.2f an hour",$ 3,$ 6 }
          其輸出將類似于:
          Joe earns $12.17 an hour

          你也可以使用一些換碼控制符格式化整行的輸出。之所以叫做換碼控制符,是因?yàn)間 a w k對(duì)這些符號(hào)有特殊的解釋。下面列出常用的換碼控制符:

          \a 警告或響鈴字符。
          \b 后退一格。
          \f 換頁(yè)。
          \n 換行。
          \r 回車。
          \t Ta b。
          \v 垂直的t a b。

          6.9 改變字段分隔符

          ???在g a w k中,缺省的字段分隔符一般是空格符或TA B。但你可以在命令行使用- F選項(xiàng)改變字符分隔符,只需在- F后面跟著你想用的分隔符即可。
          gawk -F" ;"'/tparker/{print}' /etc/passwd
          ???在此例中,你將字符分隔符設(shè)置成分號(hào)。注意: - F必須是大寫(xiě)的,而且必須在第一個(gè)引號(hào)之前。

          6.10 元字符

          g a w k語(yǔ)言在格式匹配時(shí)有其特殊的規(guī)則。例如, c a t能夠和記錄中任何位置有這三個(gè)字符的字段匹配。但有時(shí)你需要一些更為特殊的匹配。如果你想讓c a t只和c o n c a t e n a t e匹配,則需要在格式兩端加上空格:
          / cat / {print}
          再例如,你希望既和c a t又和C AT匹配,則可以使用或(|):
          / cat | CAT / {print}
          在g a w k中,有幾個(gè)字符有特殊意義。下面列出可以用在g a w k格式中的這些字符:
          ? ^ 表示字段的開(kāi)始。
          例如:$3 ~ /^b/
          ???如果第三個(gè)字段以字符b開(kāi)始,則匹配。
          ? $ 表示字段的結(jié)束。
          例如:$3 ~ /b$/
          如果第三個(gè)字段以字符b結(jié)束,則匹配。
          ? . 表示和任何單字符m匹配。
          例如:$3 ~ /i.m/
          如果第三個(gè)字段有字符i,則匹配。
          ? | 表示“或”。
          例如:/ c a t | C AT/
          和cat 或C AT字符匹配。
          ? * 表示字符的零到多次重復(fù)。
          例如:/UNI*X/
          和U N X、U N I X、U N I I X、U N I I I X等匹配。
          ? + 表示字符的一次到多次重復(fù)。
          例如:
          /UNI+X/
          和U N I X、U N I I X等匹配。
          ? \{a,b\} 表示字符a次到b次之間的重復(fù)。
          例如:
          / U N I \ { 1,3 \ } X
          和U N I X、U N I I X和U N I I I X匹配。
          ? ? 表示字符零次和一次的重復(fù)。
          例如:
          /UNI?X/
          和UNX 和U N I X匹配。
          ? [] 表示字符的范圍。
          例如:
          /I[BDG]M/
          和I B M、I D M和I G M匹配
          ? [^] 表示不在[ ]中的字符。
          例如:
          /I[^DE]M/
          和所有的以I開(kāi)始、M結(jié)束的包括三個(gè)字符的字符串匹配,除了I D M和I E M之外。

          6.11 調(diào)用gawk程序

          當(dāng)需要很多對(duì)模式和動(dòng)作時(shí),你可以編寫(xiě)一個(gè)g a w k程序(也叫做g a w k腳本)。在g a w k程序中,你可以省略模式和動(dòng)作兩邊的引號(hào),因?yàn)樵趃 a w k程序中,模式和動(dòng)作從哪開(kāi)始和從哪結(jié)束時(shí)是很顯然的。你可以使用如下命令調(diào)用g a w k程序:
          gawk -f script filename
          此命令使g a w k對(duì)文件f i l e n a m e執(zhí)行名為s c r i p t的g a w k程序。
          如果你不希望使用缺省的字段分隔符,你可以在f選項(xiàng)后面跟著F選項(xiàng)指定新的字段分隔符(當(dāng)然你也可以在g a w k程序中指定),例如,使用分號(hào)作為字段分隔符:
          gawk -f script -F";" filename
          如果希望gawk 程序處理多個(gè)文件,則把各個(gè)文件名羅列其后:
          gawk -f script filename1 filename2 filename3 ...
          缺省情況下, g a w k的輸出將送往屏幕。但你可以使用L i n u x的重定向命令使g a w k的輸出送往一個(gè)文件:
          gawk -f script filename > save_file

          6.12 BEGIN和END

          ???有兩個(gè)特殊的模式在g a w k中非常有用。B E G I N模式用來(lái)指明g a w k開(kāi)始處理一個(gè)文件之前執(zhí)行一些動(dòng)作。B E G I N經(jīng)常用來(lái)初始化數(shù)值,設(shè)置參數(shù)等。E N D模式用來(lái)在文件處理完成后執(zhí)行一些指令,一般用作總結(jié)或注釋。
          BEGIN 和E N D中所有要執(zhí)行的指令都應(yīng)該用花括號(hào)括起來(lái)。BEGIN 和E N D必須使用大寫(xiě)。
          請(qǐng)看下面的例子:
          BEGIN { print "Starting the process the file" }
          $1 == "UNIX" {print}
          $2 > 10 {printf "This line has a value of %d",$ 2 }
          END { print "Finished processing the file. Bye!"}
          此程序中,先顯示一條信息: Starting the process the file,然后將所有第一個(gè)字段等于U N I X的整條記錄顯示出來(lái),然后再顯示第二個(gè)字段大于10 的記錄,最后顯示信息: F i n i s h e dprocessing the file. Bye!。

          6.13 變量

          在g a w k中,可以用等號(hào)( = )給一個(gè)變量賦值:
          var1 = 10
          在g a w k中,你不必事先聲明變量類型。
          請(qǐng)看下面的例子:
          $1 == "Plastic" { count = count + 1 }
          如果第一個(gè)字段是P l a s t i c,則c o u n t的值加1。在此之前,我們應(yīng)當(dāng)給c o u n t賦予過(guò)初值,一般是在B E G I N部分。
          下面是比較完整的例子:
          BEGIN { count = 0 }
          $5 == "UNIX" { count = count + 1 }
          END { printf "%d occurrences of UNIX were found",count }
          變量可以和字段和數(shù)值一起使用,所以,下面的表達(dá)式均為合法:
          count = count + $6
          count = $5 - 8
          count = $5 + var1
          變量也可以是格式的一部分,例如:
          $2 > max_value {print "Max value exceeded by ",$2 -max_value}
          $4 - var1 < min_value {print "Illegal value of ",$ 4 }

          6.14 內(nèi)置變量

          g a w k語(yǔ)言中有幾個(gè)十分有用的內(nèi)置變量,現(xiàn)在列于下面:

          NR 已經(jīng)讀取過(guò)的記錄數(shù)。
          FNR 從當(dāng)前文件中讀出的記錄數(shù)。
          F I L E N A M E 輸入文件的名字。
          FS 字段分隔符(缺省為空格)。
          RS 記錄分隔符(缺省為換行)。
          OFMT 數(shù)字的輸出格式(缺省為% g)。
          OFS 輸出字段分隔符。
          ORS 輸出記錄分隔符。
          NF 當(dāng)前記錄中的字段數(shù)。

          如果你只處理一個(gè)文件,則NR 和FNR 的值是一樣的。但如果是多個(gè)文件, N R是對(duì)所有的文件來(lái)說(shuō)的,而FNR 則只是針對(duì)當(dāng)前文件而言。例如:
          NR <= 5 {print "Not enough fields in the record"}
          檢查記錄數(shù)是否小于5,如果小于5,則顯示出錯(cuò)信息。
          F S十分有用,因?yàn)镕 S控制輸入文件的字段分隔符。例如,在B E G I N格式中,使用如下的
          命令:
          F S = " : "

          6.15 控制結(jié)構(gòu)

          6.15.1 if 表達(dá)式

          if 表達(dá)式的語(yǔ)法如下:
          if (expression){
          c o m m a n d s
          }
          e l s e {
          c o m m a n d s
          }
          例如:
          # a simple if loop
          (if ($1 == 0){
          print "This cell has a value of zero"
          }
          else {
          printf "The value is %d\n",$ 1
          } )
          再看下一個(gè)例子:
          # a nicely formatted if loop
          (if ($1 > $2){
          print "The first column is larger"
          } else {
          print "The second column is larger"
          } )

          6.15.2 while 循環(huán)
          while 循環(huán)的語(yǔ)法如下:
          while (expression){
          c o m m a n d s
          }
          例如:
          # interest calculation computes compound interest
          # inputs from a file are the amount,interest_rateand years
          {var = 1
          while (var <= $3) {
          p r i n t f ( " % f \ n ",$ 1 * ( 1 + $ 2 ) ^ v a r )
          v a r + +}
          }

          6.15.3 for 循環(huán)

          for 循環(huán)的語(yǔ)法如下:
          for (initialization; expression; increment) {
          c o m m a n d
          }
          例如:
          # interest calculation computes compound interest
          # inputs from a file are the amount,interest_rateand years
          {for (var=1; var <= $3; var++) {
          p r i n t f ( " % f \ n ",$ 1 * ( 1 + $ 2 ) ^ v a r )
          }
          }
          6.15.4 next 和exit

          next 指令用來(lái)告訴gawk 處理文件中的下一個(gè)記錄, 而不管現(xiàn)在正在做什么。語(yǔ)法如下:
          { command1
          c o m m a n d 2
          c o m m a n d 3
          n e x t
          c o m m a n d 4
          }
          ???程序只要執(zhí)行到n e x t指令,就跳到下一個(gè)記錄從頭執(zhí)行命令。因此,本例中, c o m m a n d 4指令永遠(yuǎn)不會(huì)被執(zhí)行。
          ???程序遇到e x i t指令后,就轉(zhuǎn)到程序的末尾去執(zhí)行E N D,如果有E N D的話。

          6.16 數(shù)組

          g a w k語(yǔ)言支持?jǐn)?shù)組結(jié)構(gòu)。數(shù)組不必事先初始化。聲明一個(gè)數(shù)組的方法如下:
          a r r a y n a m e [ n u m ] = v a l u e
          請(qǐng)看下面的例子:
          # reverse lines in a file
          {line[NR] = $0 } # remember each line
          END {var=NR # output lines in reverse order
          while (var > 0){
          print line[var]
          v a r - -
          }
          }
          此段程序讀取一個(gè)文件的每一行,并用相反的順序顯示出來(lái)。我們使用N R作為數(shù)組的下標(biāo)來(lái)存儲(chǔ)文件的每一條記錄,然后在從最后一條記錄開(kāi)始,將文件逐條地顯示出來(lái)。

          6.17 用戶自定義函數(shù)

          復(fù)雜的gawk 程序常常可以使用自己定義的函數(shù)來(lái)簡(jiǎn)化。調(diào)用用戶自定義函數(shù)與調(diào)用內(nèi)部函數(shù)的方法一樣。函數(shù)的定義可以放在gawk 程序的任何地方。
          用戶自定義函數(shù)的格式如下:
          function name (parameter-list) {
          b o d y - o f - f u n c t i o n
          }
          name 是所定義的函數(shù)的名稱。一個(gè)正確的函數(shù)名稱可包括一序列的字母、數(shù)字、下標(biāo)線( u n d e r s c o r e s ),但是不可用數(shù)字做開(kāi)頭。p a r a m e t e r-list 是函數(shù)的全部參數(shù)的列表,各個(gè)參數(shù)之間以逗點(diǎn)隔開(kāi)。body-of-function 包含gawk 的表達(dá)式,它是函數(shù)定義里最重要的部分,它決定函數(shù)實(shí)際要做的事情。
          下面這個(gè)例子,會(huì)將每個(gè)記錄的第一個(gè)字段的值的平方與第二個(gè)字段的值的平方加起來(lái)。
          {print "sum =",S q u a r e S u m ( $ 1,$ 2 ) }
          function SquareSum(x,y) {
          s u m = x * x + y * y
          return sum
          }
          ???到此,我們已經(jīng)知道了g a w k的基本用法。g a w k語(yǔ)言十分易學(xué)好用,例如,你可以用g a w k編寫(xiě)一段小程序來(lái)計(jì)算一個(gè)目錄中所有文件的個(gè)數(shù)和容量。如果用其他的語(yǔ)言,如C語(yǔ)言,則會(huì)十分的麻煩,相反,g a w k只需要幾行就可以完成此工作。

          6.18 幾個(gè)實(shí)例

          最后,再舉幾個(gè)g a w k的例子:
          gawk '{if (NF > max) max = NF}
          END {print max}'
          此程序會(huì)顯示所有輸入行之中字段的最大個(gè)數(shù)。
          gawk 'length($0) > 80'
          此程序會(huì)顯示出超過(guò)80 個(gè)字符的每一行。此處只有模式被列出,動(dòng)作是采用缺省值顯示整個(gè)記錄。
          gawk 'NF > 0'
          顯示擁有至少一個(gè)字段的所有行。這是一個(gè)簡(jiǎn)單的方法,將一個(gè)文件里的所有空白行刪除。
          gawk 'BEGIN {for (i = 1; i <= 7; i++)
          print int(101 * rand())}'
          此程序會(huì)顯示出范圍是0 到100 之間的7 個(gè)隨機(jī)數(shù)。
          ls -l files | gawk '{x += $4}; END {print "total bytes: " x}'
          此程序會(huì)顯示出所有指定的文件的總字節(jié)數(shù)。
          expand file | gawk '{if (x < length()) x = length()}
          END {print "maximum line length is " x}'
          此程序會(huì)將指定文件里最長(zhǎng)一行的長(zhǎng)度顯示出來(lái)。expand 會(huì)將tab 改成s p a c e,所以是用實(shí)際的右邊界來(lái)做長(zhǎng)度的比較。
          gawk 'BEGIN {FS = ":"}
          {print $1 | "sort"}' /etc/passwd
          此程序會(huì)將所有用戶的登錄名稱,依照字母的順序顯示出來(lái)。
          gawk '{nlines++}
          END {print nlines}'
          此程序會(huì)將一個(gè)文件的總行數(shù)顯示出來(lái)。
          gawk 'END {print NR}'
          此程序也會(huì)將一個(gè)文件的總行數(shù)顯示出來(lái),但是計(jì)算行數(shù)的工作由g a w k來(lái)做。
          gawk '{print NR,$ 0 } '
          此程序顯示出文件的內(nèi)容時(shí),會(huì)在每行的最前面顯示出行號(hào),它的函數(shù)與‘ cat -n’類似。

          posted on 2006-06-01 14:11 bluestone 閱讀(475) 評(píng)論(0)  編輯  收藏 所屬分類: Linux工具箱

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
           
          主站蜘蛛池模板: 建瓯市| 阿荣旗| 五寨县| 县级市| 容城县| 吐鲁番市| 北流市| 都兰县| 平罗县| 右玉县| 黄梅县| 白山市| 鹤岗市| 新民市| 平罗县| 边坝县| 淮阳县| 湖口县| 承德县| 稻城县| 丰顺县| 大石桥市| 阜宁县| 高阳县| 梁河县| 商河县| 晋州市| 登封市| 沙田区| 濮阳市| 仁怀市| 宁武县| 桂东县| 广南县| 东乌珠穆沁旗| 八宿县| 乌恰县| 康保县| 桓仁| 科技| 佛坪县|