[ 永遠的UNIX::UNIX技術資料的寶庫 ]   GB | BIG5

首頁 > 編程技術 > 其它 > 正文
gawk的使用方法
不詳 (2001-04-27 13:12:55)

第一章    前言 
第二章    簡介 
第三章    讀取輸入檔案 
第四章    印出 
第五章    Patterns 
第六章    算式(Expression)作為Actions的敘述 
第七章    Actions裡面的控制敘述 
第八章    內建函式(Built-in Functions) 
第九章    使用者定義的函式 
第十章    □例 
第十一章  結論 
 
 
 
======================================= 
 
第一章  前言 
 
    awk 是一個程式語言,對於資料的處理具有很強的功能。對於文 
字檔裡的資料做修改、比對、抽取等的處理,awk 能夠以很短的程式 
輕易地完成。如果使用 C 或 Pascal 等語言寫程式完成上述的動作, 
會不方便且很花費時間,所寫的程式也會很大。 
 
    awk 能夠依照使用者的定義格式來分解輸入資料,也可依照使用 
者定義的格式來印出資料。 
 
    awk 名稱的由來是由它的原始設計者的姓氏之第一個字母而命名 
:Alfred V. Aho, Peter J. Weinberger, Brian W. Kernighan。 
awk最初在1977年完成。一個新版本的awk在1985年被發表,它的功能 
比舊版本增強不少。 
 
    gawk 是GNU所做的 awk,gawk 最初在1986年完成,之後不斷地 
被改進、更新。gawk 包含 awk 的所有功能。 
 
    往後的 gawk 將以下面的2個輸入檔案來做例子說明。 
 
檔案'BBS-list': 
aardvark     555-5553     1200/300           B 
alpo-net     555-3412     2400/1200/300      A 
barfly       555-7685     1200/300           A 
bites        555-1675     2400/1200/300      A 
camelot      555-0542     300                C 
core         555-2912     1200/300           C 
fooey        555-1234     2400/1200/300      B 
foot         555-6699     1200/300           B 
macfoo       555-6480     1200/300           A 
sdace        555-3430     2400/1200/300      A 
sabafoo      555-2127     1200/300           C 
 
 
檔案'shipped': 
Jan  13  25  15 115 
Feb  15  32  24 226 
Mar  15  24  34 228 
Apr  31  52  63 420 
May  16  34  29 208 
Jun  31  42  75 492 
Jul  24  34  67 436 
Aug  15  34  47 316 
Sep  13  55  37 277 
Oct  29  54  68 525 
Nov  20  87  82 577 
Dec  17  35  61 401 
 
Jan  21  36  64 620 
Feb  26  58  80 652 
Mar  24  75  70 495 
Apr  21  70  74 514 
 
 
 
第二章  簡介 
 
    gawk 的主要功能是針對檔案的每一行(line)搜尋指定的 patterns 
。當一行裡有符合指定的 patterns,gawk 就會在此一行執行被指定 
的 actions。 gawk 依此方式處理輸入檔案的每一行直到輸入檔案結 
束。 
 
    gawk 程式是由很多的 pattern 與 action 所組成,action 寫在 
大括號 { } 裡面,一個pattern後面就跟一個action。整個 gawk 程 
式會像下面的樣子: 
 
            pattern      {action} 
            pattern      {action} 
 
    在 gawk 程式裡面的規則,pattern 或 action 能夠被省略,但 
是兩個不能同時被省略。如果 pattern 被省略,對於輸入檔裡面的 
每一行,action 都會被執行。如果 action 被省略,內定的 action 
則會印出所有符合 pattern 的輸入行。 
 
 
 
  2.1 如何執行gawk程式 
 
    基本上,有2個方法可以執行gawk程式。 
 
    □如果 gawk 程式很短,則 gawk 可以直接寫在 command line,如下所示: 
 
          gawk 'program' input-file1 input-file2 ... 
 
      其中 program 包括一些 pattern 和 action。 
 
    □如果 gawk 程式較長,較為方便的做法是將 gawk 程式存在一個檔案, 
      即 patterns 與 actions 寫在檔名為 program-file 的檔案裡面,執行 
      gawk 的格式如下所示: 
 
          gawk -f program-file input-file1 input-file2 ... 
 
      gawk 程式的檔案不止一個時,執行gawk 的格式如下所示: 
 
          gawk -f program-file1 -f program-file2 ... input-file1 
               input-file2 ... 
 
 
 
  2.2 一個簡單的例子 
 
    現在我們舉一個簡單的例子,因為 gawk 程式很短,所以將 gawk 程 
式直接寫在 command line。 
 
    gawk '/foo/ {print $0}' BBS-list 
 
實際的 gawk 程式為 /foo/ {print $0}。/foo/ 為 pattern,意思為搜 
尋輸入檔裡的每一行是否含有子字串 'foo',如果含有 'foo' 則執行 action。 
action 為 print $0,是將現在這一行的內容印出。BBS-list 是輸入的檔案。 
 
    執行完上述指令後,會印出下面的結果: 
fooey        555-1234     2400/1200/300      B 
foot         555-6699     1200/300           B 
macfoo       555-6480     1200/300           A 
sabafoo      555-2127     1200/300           C 
 
 
 
  2.3 一個較復雜的例子 
 
        gawk '$1 == "Feb" {sum=$2+$3}  END {print sum}'  shipped 
 
    現在這個例子會將輸入檔 'shipped' 的第一個欄位與 "Feb" 做比較 
,如果相等,則其對應的第2欄位與第3欄位的值會被加到變數 sum。 
對於輸入檔的每一行重復上述的動作,直到輸入檔的每一行都被處理 
過為止。最後將 sum 的值印出。END {print sum} 的意思為在所有的輸 
入讀完之後,執行一次 print sum 的動作,也就是把 sum 的值印出。 
 
    下面是執行的結果: 
84 
 
                                                             
第三章  讀取輸入檔案                                           
                                                                 
    gawk的輸入可以從標準輸入或指定的檔案裡讀取。輸入的讀取單       
位被稱為”記錄”(records),gawk 在做處理時,是一個記錄一個記                                                                    (p9 of 46) 
錄地處理。每個記錄的內定值是一行(line),一個記錄又被分為多個   
欄位(fields)。                                                                 
                                                                  
                                                                        
                                                                 
  3.1 如何將輸入分解成記錄(records)                              
                                                               
    gawk 語言會把輸入分解成記錄(record)。記錄與記錄之間是以            
record separator 隔開,record separator 的內定值是表示新一行的  
字元(newline character),因此內定的 record separator 使得文字             
的每一行是一個記錄。                                                   
                                                                      
    record separator 隨內建變數 RS 的改變而改變。RS 是一個字串, 
它的內定值是"\n"。僅有 RS 的第一個字元是有效的,它被當作 record 
separator,而 RS 的其它字元會被忽略。                        
                                                             
    內建變數 FNR 會儲存目前的輸入檔案已頸歡寥〉募鍬賈鍪D  
建變數 NR 會儲存目前為止所有的輸入檔案已頸歡寥〉募鍬賈鍪     
                                                              
  3.2 欄位(field)                                                              
                                                                  
    gawk 會自動將每個記錄分解成多個欄位 (field)。類似於字在一           
行裡面,gawk 的內定動作會認為欄位之間是以 whitespace 分開。在    
gawk 裡,whitespace 的意思是一個或多個空白或 tabs。              
                                                               
    在 gawk 程式裡面,以'$1'表示第一個欄位,'$2'表示第二個欄位         
,依此類推。舉個例子,假設輸入的一行如下所示:                  
                                                                          
        This seems like a pretty nice example.                         
                                                                      
第一個欄位或 $1 是'This',第二個欄位或 $2 是 'seems',依此類推。   
有個地方值得特別注意,第七個欄位或 $7 是'example.'而非'example'。 
                                                             
    不論有多少欄位,$NF 可用來表示一個記錄的最後一個欄位。以 
上面的例子為例,$NF 與 $7 相同,也就是'example.'。             
                                                                 
    NF 是一個內建變數,它的值表示目前這個記錄之欄位的個數。  $0,看起來好像是第零個欄位,它是一個特例,它表示整個記錄。 
                                                                               
    下面是一個較復雜的例子:                                      
                                                                        
        gawk '$1~/foo/ {print $0}' BBS-list                      
                                                                 
    結果如下:                                                 
fooey        555-1234     2400/1200/300      B                         
foot         555-6699     1200/300           B                  
macfoo       555-6480     1200/300           A                            
sabafoo      555-2127     1200/300           C                         
                                                                      
這個例子是把輸入檔'BBS-list'的每個記錄的第一個欄位作檢查,如       
果它含有子字串'foo',則這一個記錄會被印出。                       
                                                             
                                                             
                                                               
  3.3 如何將記錄分解成欄位                                       
                                                                   
    gawk 根據 field separator 將一個記錄分解成欄位。field sepa- rator 以內建變數 FS 表示。                                     
                                                                               
    舉個例子,假如 field separator 是'oo',則下面的行:           
                                                                        
        moo goo gai pan                                          
                                                                 
會被分成三個欄位:'m'、' g'、' gai pan'。                      
                                                                       
    在 gawk 程式裡,可以使用'='來改變 FS 的值。例如:            
                                                                          
        gawk 'BEGIN {FS=","}; {print $2}'                              
                                                                      
輸入行如下:                                                       
                                                                  
        John Q. Smith, 29 Oak St., Walamazoo, MI 42139       
                                                             
執行gawk的結果將印出字串 ' 29 Oak St.'。BEGIN 後面的 action 會在 
第一個記錄被讀取之前執行一次。                                                                                      
第四章  印出                                                                   
                                                                  
    在gawk程式裡,actions 最常做的事就是印出(printing)。簡單            
的印出,使用 printe敘述。復雜格式的印出,使用 printf 敘述。      
                                                                 
                                                               
                                                                       
  4.1 print敘述                                                 
                                                                          
    print 敘述用在簡單、標準的輸出格式。敘述的格式如下所示:           
                                                                      
        print item1, item2, ...                                    
                                                                  
輸出時,各個 item 之間會以一個空白分開,最後會換行(newline)。 
                                                             
    如果 'print'敘述之後沒有跟任何東西,它與'print $0'的效     
果一樣,它會印出現在的記錄(record)。要印出空白行可使用'print     
""'。 印出一段固定的文字,可用雙引號將文字的兩邊括起來,例如       
'print "Hello there"'。                          
 這裡是一個例子,它會把每個輸入記錄的前二個欄位印出:                       
                                                                  
        gawk '{print $1,$2}' shipped                                    
                                                                 
    結果如下所示:                                               
Jan 13                                                         
Feb 15                                                                 
Mar 15                                                          
Apr 31                                                                    
May 16                                                                 
Jun 31                                                                
Jul 24                                                             
Aug 15                                                            
Sep 13                                                        
Oct 29                                                       
Nov 20                                                           
Dec 17                                                           
                                               
Feb 26                                                         
Mar 24                                                                         
Apr 21                                                            
                                                                        
                                                                 
                                                                 
  4.2 Output Separators                                        
                                                                       
    前面我們已提過如果 print 敘述包含有多個 item,item 之間     
用逗點分開,則印出時各個item會被一個空白隔開。你能夠使用任何              
的字串作為 output field separator,可以居贍誚涫?nbsp;OFS 的設            
定來更改 output field separator。OFS 的初始值為" ",即一格的          
空白。                                                             
                                                                  
    整個 print 敘述的輸出被稱為 output record。print 敘述輸   
出 output record 之後,會接輸出一個字串,此字串稱為 output 
record separator。內建變數 ORS 用來指明此字串。ORS 的初始值      
為 "\n",也就是換行。                                            
                                                                   
    下面這個例子會印出每個記錄的第一個欄位和第二個欄位,此二   
                                                                   (p16 of 46) 
個欄位之間以分號';'分開,每行輸出之後會加入一個空白行。        
                                                                               
        gawk 'BEGIN {OFS=";"; ORS="\n\n"} {print $1, $2}' BBS-list 
                                                                        
    結果如下所示:                                               
aardvark;555-5553                                                
                                                               
alpo-net;555-3412                                                      
                                                                
barfly;555-7685                                                           
                                                                       
bites;555-1675                                                        
                                                                   
camelot;555-0542                                                  
                                                              
core;555-2912                                                
                                                                 
fooey;555-1234                                                   
                                                                   
foot;555-6699                      
                                                              
macfoo;555-6480                                                              
                                                                   
sdace;555-3430                                                          
                                                                 
sabafoo;555-2127                                                 
                                                               
                                                                       
                                                                
                                                                          
  4.3 printf敘述                                                       
                                                                      
    printf 敘述會使得輸出格式較容易精確地控制。printf 敘述可以     
指定每個 item 印出的寬度,也可以指定數字的各種型式。              
                                                              
    printf 敘述的格式如下:                                  
                                                                 
        printf format, item1, item2, ...                         
                                                                   
    print 與 printf 的差別是在於 format, printf 的引數比 print   
                                                                   (p18 of  
多了字串 format。format 的型式與 ANSI C 的 printf 之格式相同。 
                                                                             
    printf 並不會做自動換行的動作。內建變數 OFS 與 ORS 對 printf 敘 
述沒有任何影響。                                                        
                                                                 
    格式的指定以字元'%'開始,後面接格式控制字母。              
                                                               
    格式控制字母如下所示:                                             
                                                                
'c' 將數字以 ASCII 字元印出。                                             
    例如'printf "%C",65'會印出字元'A'。                                
                                                                      
'd' 印出十進位的整數。                                             
                                                                  
'i' 印出十進位的整數。                                        
                                                             
'e' 將數字以科學符號的形式印出。                                 
    例如                                                         
                                                                   
      print "$4.3e",1950                    
                                                                   (p19 of  
                                                               
    結果會印出'1.950e+03'。                                                  
                                                                    
'f' 將數字以浮點的形式印出。                                            
                                                                 
'g' 將數字以科學符號的形式或浮點的形式印出。數字的絕對值如果     
    大於等於0.0001則以浮點的形式印出,否則以科學符號的形式印   
    出。                                                               
                                                                
'o' 印出無號的八進位整數。                                                
                                                                       
's' 印出一個字串。                                                    
                                                                   
'x' 印出無號的十六進位整數。10至15以'a'至'f'表示。                
                                                              
'X' 印出無號的十六進位整數。10至15以'A'至'F"表示。           
                                                                 
'%' 它並不是真正的格式控制字母,'%%"將印出"%'。                  
                                                                   
    在 % 與格式控制字母之間可加入 modifier,modifier 是用來進一 
步控制輸出的格式。可能的 modifier 如下所示:                   
                                                                             
'-'     使用在 width 之前,指明是向左靠齊。如果'-'沒有出現,則會在  
        被指定的寬度向右靠齊。例如:                                    
                                                                 
            printf "%-4S", "foo"                                 
                                                               
        會印出'foo '。                                                 
                                                                
'width' 這一個數字指示相對應的欄位印出時的寬度。例如:                    
                                                                       
            printf "%4s","foo"                                        
                                                                   
        會印出' foo'。                                            
                                                              
        width 的值是一個最小寬度而非最大寬度。如果一個 item 的 
        值需要的寬度比 width 大,則不受 width 的影響。例如       
                                                                 
            printf "%4s","foobar"                    
    將印出'foobar'。                                       
                                                                             
'.prec' 此數字指定印出時的精確度。它指定小數點右邊的位數。如        
        果是要印出一個字串,它指定此字串最多會被印出多少個字            
        元。                                                     
                                                                 
                                                               
                                                                       
第五章  patterns                                                
                                                                          
    在 gawk 程式裡面,當 pattern 符合現在的輸入記錄(record),其        
相對應的 action 才會被執行。                                          
                                                                   
                                                                  
                                                              
  5.1 Pattern的種類                                            
                                                                 
    這裡對 gawk 的各種 pattern 型式作一整理:                    
                                                                   
/regular expression/                                    
                                                                  (p22 of  
    一個 regular expression 當作一個 pattern。每當輸入記錄 (   
    record)含有 regular expression 就視為符合。                              
                                                                    
expression                                                              
    一個單一的 expression。當一個值不為 0 或一個字串不是空的,   
    則可視為符合。                                               
                                                               
pat1,pat2                                                              
    一對的 patterns 以逗號分開,指定記錄的□圍。                
                                                                          
BEGIN                                                                  
END                                                                   
    這是特別的 pattern, gawk 在開始執行或要結束時會分別執行相      
    對應於BEGIN或END的 action。                                   
                                                              
null                                                           
    這是一個空的pattern,對於每個輸入記錄皆視為符合pattern。     
                                                        
                                                                   (p23 of  
  5.2 Regular Expressions當作Patterns                          
                                                                             
    一個 regular expression 可簡寫為 regexp,是一種描述字串的方     
法。一個 regular expression 以斜線('/')包圍當作 gawk 的 pattern。       
                                                                 
    如果輸入記錄含有 regexp 就視為符合。例如:pattern 為 /foo/, 
對於任何輸入記錄含有'foo'則視為符合。                          
                                                                       
    下面的例子會將含有'foo'的輸入記錄之第2個欄位印出。          
                                                                          
        gawk '/foo/ {print $2}' BBS-list                               
                                                                      
    結果如下:                                                     
555-1234                                                          
555-6699                                                      
555-6480                                                       
555-2127                                                         
                                                                 
    regexp 也能使用在比較的算式。                                  
                                             
                                                                   (p24 of  
exp ~ /regexp/                                                 
    如果 exp 符合 regexp,則結果為真(true)。                                 
                                                                    
exp !~ /regexp/                                                         
    如果 exp 不符合 regexp,則結果為真。                         
                                                                 
                                                               
                                                                       
  5.3 比較的算式當作Patterns                                    
                                                                          
    比較的 pattern 用來測試兩個數字或字串的關系諸如大於、等於          
、小於。下面列出一些比較的pattern:                                   
                                                                   
xx<=y  如果 x 小於、等於 y,則結果為真。                       
x>y   如果 x 大於 y,則結果為真。                              
x>=y  如果 x 大於、等於 y,則結果為真。                          
x==y  如果 x 等於 y,則結果為真。                                
x!=y  如果 x 不等於 y,則結果為真。                                
x~y   如果 x 符合 regular expression y,則結果為真。 
                                                                  (p25 of  
x!~y  如果 x 不符合 regular expression y,則結果為真。         
                                                                             
    上面所提到的 x 與 y,如果二者皆是數字則視為數字之間的比較,     
否則它們會被轉換成字串且以字串的形式做比較。兩個字串的比較,            
會先比較第一個字元,然後比較第二個字元,依此類推,直到有不同     
的地方出現為止。如果兩個字串在較短的一個結束之前是相等,則視     
為長的字串比短的字串大。例如 "10" 比 "9" 小,"abc" 比 "abcd" 小。 
                                                                       
                                                                
                                                                          
  5.4 使用布林運算的Patterns                                           
                                                                      
    一個布林(boolean) pattern 是使用布林運算"或"('||'),"及"       
('&&'),"反"('!')來組合其它的pattern。                            
例如:                                                        
                                                               
    gawk '/2400/ && /foo/' BBS-list                              
    gawk '/2400/ || /foo/' BBS-list                              
    gawk '! /foo/' BBS-list                              
                                                              
                                                                             
第六章  算式(Expression)作為Actions的敘述                           
                                                                        
    算式(Expression) 是gawk程式裡面action的基本構成者。          
                                                                 
                                                                  
                                                                       
  6.1 算術運算                                                  
                                                                          
    gawk 裡的算術運算如下所示:                                        
                                                                      
x+y  加                                                            
x-y  減                                                           
-x   負                                                       
+x   正。實際上沒有任何影響。                                  
x*y  乘                                                          
x/y  除                                                          
x%y  求餘數。例如 5%3=2。                                          
x^y                                       
x**y x 的 y 次方。例如2^3=8。                                  
                                                                             
                                                                    
                                                                        
  6.2 比較算式與布林算式                                         
                                                                 
    比較算式 (comparison expression) 用來比較字串或數字的關系     
,運算符號與 C 語言相同。表列如下:                                    
                                                                
xx<=y                                                                   
x>y                                                                   
x>=y                                                               
x==y                                                              
x!=y                                                          
x~y                                                            
x!~y                                                             
                                                                 
比較的結果為真(true)則其值是 1。否則其值是 0。     
   布林算式(boolean expression)有下面三種:                   
                                                                             
boolean1 && boolean2                                                
boolean1 || boolean2                                                    
! boolean                                                        
                                                                 
                                                                  
                                                                       
  6.3 條件算式(Conditional Expressions)                         
                                                                          
    一個條件式算式是一種特別的算式,它含有3個運算元。                  
    條件式算式與C語言的相同:                                         
                                                                   
        selector ? if-true-exp : if-false-exp                     
                                                              
它有3個子算式。第一個子算式selector 首先會被計算。如果是真,    
則if-true-exp會被計算且它的值變成整個算式的值。否則if-false-     
exp 會被計算且它的值變成整個算式的值。                           
                                                                   
    例如下面的例子會產生x的絕對值:            
   x>0 ? x : -x                                                         
                                                                    
                                                                        
                                                                 
第七章  Actions裡面的控制敘述                                    
                                                                  
    在 gawk 程式裡面,控制敘述諸如 if、while 等控制程式執行的流        
程。在 gawk 裡的控制敘述與 C 的類似。                           
                                                                          
    很多的控制敘述會包括其它的敘述,被包括的敘述稱為 body。假          
如 body 裡面包括一個以上的敘述,必須以大括弧 { } 將這些敘述括起       
來,而各個敘述之間需以換行(newline)或分號隔開。                    
                                                                  
                                                              
                                                               
  7.1 if 敘述                                                    
                                                                 
        if (condition) then-body [else else-body]   
                                                                   (p30 of  
如果 condition 為真(true),則執行 then-body,否則執行 else-body。 
                                                                             
    舉一個例子如下:                                                
                                                                        
        if (x % 2 == 0)                                          
           print "x is even"                                     
        else                                                      
           print "x is odd"                                            
                                                                
                                                                          
                                                                       
  7.2 while 敘述                                                      
                                                                   
        while (condition)                                         
           body                                               
                                                               
while 敘述做的第一件事就是測試 condition。假如 condition 為真則  
執行 body 的敘述。body 的敘述執行完後,會再測試 condition,假如  
condition 為真,則 body 會再度被執行。這個過程會一直被重復直到     
condition 不再是真。如果 condition 第一次測試就是偽(false),則  
body 從沒有被執行。                                               
                                                                             
    下面的例子會印出每個輸入記錄(record)的前三個欄位。              
                                                                        
        gawk '{ i=1                                              
                while (i <= 3) {                                 
                    print $i                                      
                    i++                                                
                }                                               
              }'                                                          
                                                                       
                                                                      
                                                                   
  7.3 do-while 敘述                                               
                                                              
        do                                                     
           body                                                  
        while (condition)                                        
                                                                   
這個 do loop 執行 body 一次,然後只要 condition 是真則會重復執行 body。 
                                                                   (p32 of  
即使開始時 condition 是偽,body 也會被執行一次。                  
                                                                             
    下面的例子會印出每個輸入記錄十次。                              
                                                                        
        gawk '{ i= 1                                             
                do {                                             
                   print $0                                       
                   i++                                                 
                } while (i <= 10)                               
        }'                                                                
                                                                       
                                                                      
                                                                   
  7.4 for 敘述                                                    
                                                              
        for (initialization; condition; increment)             
           body                                                  
                                                                 
此敘述開始時會執行initialization,然後只要 condition是真,它       
會重復執行body與做increment 。                                  
                                                               
    下面的例子會印出每個輸入記錄的前三個欄位。                               
                                                                    
        gawk '{ for (i=1; i<=3; i++)                                    
                   print $i                                      
        }'                                                       
                                                                  
                                                                       
                                                                
  7.5 break 敘述                                                          
                                                                       
    break 敘述會跳出包含它的 for、while、do-while 回圈的最內層。      
                                                                   
    下面的例子會找出任何整數的最小除數,它也會判斷是否為質數。    
                (http://www.fanqiang.com)
    進入【UNIX論壇

相關文章
 

★  樊強制作 歡迎分享  ★