awk線上例項入門教程 第一部分

helloxchen發表於2010-10-21
awk線上例項入門教程 第一部分
———一種名稱很奇特的優秀語言介紹

Awk 是一種名稱奇怪但功能強大的語言。本系列文章是一個包含三部分(分別釋出至本帖1#, 2#, 3#樓)。本文將使您迅速掌握 awk 程式設計技巧。隨著本系列的進展,將討論更高階的主題,最後將演示一個真實的高階 awk 應用程式。

捍衛 awk

在這一系列的文章中,我將使您成為精通 awk 的程式設計人員。我承認,awk 並沒有一個非常好聽且又非常 “時髦” 的名字。awk 的 GNU 版本(叫作 gawk)聽起來非常怪異。那些不熟悉這種語言的人可能聽說過 "awk",而且可能認為它是一組落伍且過時的混亂程式碼。它甚至會使最博學的 UNIX 權威陷於混亂的邊緣(使他不斷地發出 "kill -9!" 命令,就象使用咖啡機一樣)。

的確,awk 沒有一個動聽的名字。但它是一種很棒的語言。awk 適合於文字處理和報表生成,它還有許多精心設計的特性,允許進行多種方式的程式設計。與某些語言不同,awk 的語法較為常見。它借鑑了某些語言的一些精華部分,如 C 語言、python 和 bash(雖然在技術上,awk 比 python 和 bash 早建立)。awk 是一種一旦學會就會成為您戰略程式碼庫的重要部分的語言。

第一個 Awk

您應該會看到 /ect/passwd 檔案中的內容,本文使用該檔案來解釋 awk 的工作原理。當呼叫 awk 時,我們指定 /etc/passwd 作為輸入檔案。Awk 在執行期間對 /etc/passwd 檔案中的每一行依次執行 print 命令。所有輸出都傳送到 stdout,可以得到類似 cat 命令的結果。

現在解釋程式碼塊 { print }。在 Awk 中,花括號用於將程式碼分塊,這與 C 語言類似。我們的程式碼塊中只有一條 print 命令。在 Awk 中,當 print 命令單獨出現時,將列印當前行的全部內容。
  1. $ awk '{ print $0 }' /etc/passwd
複製程式碼
在 Awk 中,變數 $0 表示整個當前行,因此 print 和 print $0 的作用完全相同。
  1. $ awk '{ print "" }' /etc/passwd
複製程式碼
  1. $ awk '{ print "hiya" }' /etc/passwd
複製程式碼
執行該指令碼,螢幕上講顯示多行。

多個欄位

print $1
  1. $ awk -F":" '{ print $1 $3 }' /etc/passwd
複製程式碼
halt7
operator11
root0
shutdown6
sync5
bin1
....etc.



print $1 $3
  1. $ awk -F":" '{ print $1 " " $3 }' /etc/passwd
複製程式碼
$1 $3
  1. $ awk -F":" '{ print "username: " $1 "ttuid:" $3 }' /etc/passwd
複製程式碼
username: halt uid:7
username: operator uid:11
username: root uid:0
username: shutdown uid:6
username: sync uid:5
username: bin uid:1
....etc.
外部指令碼
  1. BEGIN {
  2. FS=":"
  3. }
  4. { print $1 }
複製程式碼
兩種方法的區別在於如何設定欄位分隔符。在該指令碼中,(透過設定 FS 變數)在程式碼中指定欄位分隔符,而前一示例透過在命令列向 awk 傳遞 -F":" 選項來設定 FS。一般而言,最好在指令碼內部設定欄位分隔符,因為這樣可以少輸入一個命令列引數。本文稍後將深入講解 FS 變數。

BEGIN 與 END 程式碼塊

通常,awk 會針對每個輸入行執行一次每個程式碼塊。但是,在許多程式設計情形下,可能需要在 awk 開始處理輸入檔案的文字之前 執行初始化程式碼。對這種情況,awk 支援定義 BEGIN 程式碼塊。前一示例使用了這種程式碼塊。因為 BEGIN 程式碼塊在 awk 開始處理輸入檔案之前執行,因此它是初始化 FS(欄位分隔符)變數、列印頁首或者初始化在後續程式中將要引用的其他全域性變數的絕佳位置。

另外,awk 還提供了另一種稱為 END 的專用程式碼塊。在輸入檔案的所有行處理完畢之後,awk 執行這個程式碼塊。通常,END 程式碼塊用於進行最終計算或者列印應該在輸出流結尾處出現的彙總資訊。

正規表示式與程式碼塊
  1. /foo/ { print }
複製程式碼
  1. /[0-9]+.[0-9]*/ { print }
複製程式碼
表示式與程式碼塊
fred print
  1. $1 == "fred" { print $3 }
複製程式碼
root
  1. $5 ~ /root/ { print $3 }
複製程式碼
條件語句
  1. if
  2. {
  3. if ( $5 ~ /root/ ) {
  4. print $3
  5. }
  6. }
複製程式碼
兩個指令碼的作用相同。第一個示例的布林表示式位於程式碼塊外,而第二個示例的程式碼塊會針對每個輸入行執行一次,本文使用 if 語句有選擇地執行列印命令。兩種方法都可以使用,可以選擇與指令碼的其他部分最匹配的方法。
if if
  1. {
  2. if ( $1 == "foo" ) {
  3. if ( $2 == "foo" ) {
  4. print "uno"
  5. } else {
  6. print "one"
  7. }
  8. } else if ($1 == "bar" ) {
  9. print "two"
  10. } else {
  11. print "three"
  12. }
  13. }
複製程式碼
if
  1. ! /matchme/ { print $1 $3 $4 }
複製程式碼
  1. {
  2. if ( $0 !~ /matchme/ ) {
  3. print $1 $3 $4
  4. }
  5. }
複製程式碼
兩個指令碼都會只輸出不 包含 matchme 字元序列的行。也可以選擇最適合您的程式碼的方法。它們的功能完全相同。
  1. ( $1 == "foo" ) && ( $2 == "bar" ) { print }
複製程式碼
該示例只列印第一個欄位等於 foo 且 第二欄位等於 bar 的行。

數值變數!

在 BEGIN 程式碼塊中,我們將整型變數 x 初始化為零。這樣,awk 每次遇到空白行時都將執行 x=x+1 語句,遞增 x 值。在所有行都處理完畢之後,awk 執行 END 程式碼塊,並列印最終的彙總資訊,以顯示它找到的空白行數。

字串化變數

2.01


1.01 x $( ) 1.01
  1. { print ($1^2)+1 }
複製程式碼
稍做試驗就可以發現,如果特定變數不包含效數字,那麼 awk 在計算數學表示式時將該變數當作數值零處理。

眾多運算子

Awk 的另一個優點是它擁有全面的數學運算子。除了標準的加減乘除,awk 還支援前面演示的指數運算子 “^”、求模(餘數)運算子 “%” 和借鑑自 C 語言的大量方便的賦值運算子。

其中包括前後加/減(i++、--foo),加減乘除賦值運算子(a+=3、b*=2、c/=2.2、d-=6.2)。而且,這僅僅是一部分 —— 我們還能使用方便的求模/指數賦值運算子(a^=2、b%=4)。

欄位分隔符

Awk 有其自己的特殊變數集合。其中一些變數支援調優 awk 效能,而且可以讀取另一些變數來收集關於輸入的重要資訊。前面已經接觸過特殊變數 FS。如前所述,這個變數支援設定 awk 期望在欄位中找到的字元序列。當我們使用 /ect/passwd 作為輸入時,FS 設為 ":"。儘管這樣做可以解決問題,但 FS 還支援更高的靈活性。
  1. FS="t+"
複製程式碼
上面使用特殊的正規表示式字元 “+”,表示 “一個或多個前一字元”。
  1. FS="[[:space:]+]"
複製程式碼
儘管該賦值運算子能夠解決問題,但是並非必要。為什麼呢?因為在預設情況下,FS 被設為單個空格字元,awk 將其解釋為 “一個或多個空格或製表符”。在這個特定的示例中,預設的 FS 設定恰好是您最想要的設定。
  1. FS="foo[0-9][0-9][0-9]"
複製程式碼
欄位數目
  1. {
  2. if ( NF > 2 ) {
  3. print $1 " " $2 ":" $3
  4. }
  5. }
複製程式碼
記錄數目
  1. {
  2. #skip header
  3. if ( NR > 10 ) {
  4. print "ok, now for the real information!"
  5. }
  6. }
複製程式碼
Awk 還提供了一些具有多種用途的其他變數。後續文章中將深入講解這些變數。

我們對 awk 的初次探究現在就結束了。隨著本系列的延續,我將演示更高階的 awk 功能,我們將用一個真實的 awk 應用程式作為本系列的結尾。同時,如果急於學習更多知識,請參考下面列出的參考資料。
[@more@]

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/24790158/viewspace-1040122/,如需轉載,請註明出處,否則將追究法律責任。

相關文章