作者: Dong | 可以轉載, 但必須以超連結形式標明文章原始出處和作者資訊及 著作權聲明
網址: http://dongxicheng.org/script/awk-usage/
1. 什麼是awk
awk是Unix/Linux提供的樣式掃描與處理工具,非常擅長處理結構化資料和產生表單。與sed 和grep 很相似,但功能卻超過大於兩者,由於awk具備各種指令碼語言的特點,所以也可以把它看做一種指令碼語言。本文介紹了awk的使用方法。
2. awk程式設計模型
awk程式由三部分組成,分別為:初始化(處理輸入前做的準備,放在BEGIN塊中),資料處理(處理輸入資料),收尾處理(處理輸入完成後要進行的處理,放到END塊中)。其中,在“資料處理”過程中,指令被寫成一系列模式/動作過程,模式是用於測試輸入行的規則,以確定是否將應用於這些輸入行。
3. awk調用方式
主要有三種調用方式,分別為:
(1) awk 命令列
你可以象使用普通UNIX 命令一樣使用awk,在命令列中你也可以使用awk 程式設計語言,,這種方法一般只用於解決簡單的問題。當然,你也可以在shell script 程式中引用awk 命令列甚至awk 程式指令碼。
(2) 使用-f 選項調用awk 程式
awk 允許將一段awk 程式寫入一個文字檔,然後在awk 命令列中用-f 選項調用並執行這段程式。
(3) 利用命令直譯器調用awk 程式
利用UNIX 支援的命令直譯器功能,我們可以將一段awk 程式寫入文字檔,然後在它的第一行加上#!/bin/awk –f.
4. awk文法
與其它 UNIX 命令一樣,awk 擁有自己的文法:
awk [ -F re] [parameter...] ['prog'] [-f progfile][in_file...]
(1) -F re:允許awk 更改其欄位分隔符號。
(2) parameter:該參數協助為不同的變數賦值。
(3) ‘prog’:awk 的程式語句段。這個語句段必須用單拓號:’和’括起,以防被shell 解釋。這個程式語句段的標準形式為:’pattern {action}’
其中pattern 參數可以是egrep Regex中的任何一個,它可以使用文法/re/再加上一些樣式匹配技巧構成。與sed 類似,你也可以使用”,”分開兩樣式以選擇某個範圍。action 參數總是被大括弧包圍,它由一系列awk 語句組成,各語句之間用”;”分隔。awk 解釋它們,並在pattern 給定的樣式匹配的記錄上執行其操作。你可以省略pattern 和action 之一,但不能兩者同時省略,當省略pattern 時沒有樣式匹配,表示對所有行(記錄)均執行操作,省略action時執行預設的操作——在標準輸出上顯示。
(4) -f progfile:允許awk 調用並執行progfile 指定有程式檔案。progfile 是一個文字檔,它必須符合awk 的文法。
(5) in_file:awk的輸入檔案,awk 允許對多個輸入檔案進行處理。值得注意的是awk 不修改輸入檔案。如果未指定輸入檔案,awk 將接受標準輸入,並將結果顯示在標準輸出上。
5. awk指令碼編寫
5.1 awk的內建變數
awk中有兩類內建的變數,一類使用者可根據需要改變,主要有:FS:輸入資料的欄位分割符,RS:輸入資料的記錄分隔字元,OFS:輸輸出資料的欄位分割符,ORS:輸出資料的記錄分隔字元;另一類是系統自動改變的,如:NF:目前記錄的欄位個數,NR:目前記錄編號等。
舉例說明:
awk -F”:” ‘{ print $1 ” ” $3 }’ /etc/passwd #列印passwd中的第1,3個欄位
5.2 pattern/action模式
awk程式部分採用了pattern/action模式,即,針對匹配pattern的資料,使用action邏輯進行處理。
舉例說明:
/^$/ {print “This is a blank line!”} #判斷當前是不是空格
$5 ~ /MA/ {print $1 “,” $3} #判斷第5個欄位是不是含有“MA”
NF == 3 { print “this particular record has three fields: ” $0 }
5.3 BEGIN和 END
在 awk中兩個特別的運算式,BEGIN和 END,這兩者都可用於 pattern中,提供 BEGIN 和 END 的作用是給程式賦予初始狀態和在程式結束之後執行一些掃尾的工作。任何在 BEGIN 之後列出的操作(在{}內)將在 awk 開始掃描輸入之前執行,而 END 之後列出的操作將在掃描完全部的輸入之後執行。因此,通常使用BEGIN來初始設定變數,使用END 來輸出最終結果。
例:累計銷售檔案xs 中的銷售金額(假設銷售金額在記錄的第三欄位) :
$awk
>’BEGIN { FS=”:”;print “統計銷售金額”;total=0}
>{print $3;total=total+$3;}
>END {printf “銷售金額總計:%.2f”,total}’ sx
5.4 迴圈語句
Awk中的迴圈語句與C很相似,包括do…while,for,continue/break,while等
5.5 條件陳述式
Awk中的條件陳述式與C相似,但它有更好地支援。
舉例說明:
if(x ~ /[yY](es) ?/) print x #如果x符合pattern “[yY](es) ?”,則列印出來
{ if ( $0 !~ /matchme/ ) { print $1 $3 $4}} #如果$0不包含“matchme”,則列印第1,3,4個欄位
5.6 函數
(1) 數學函數
Awk中包含豐富的數學函數,包括:cos(x),sin(x),log(x),….
(2) 字串函數
Awk中包含豐富的字串函數,如:
length(x):求字串x的長度
index(t,s):返回字串s在字串t中的位置
match(s,r):Regexr在字串s中出現位置
…
(3) 自訂函數
awk允許自訂函數,文法是:function name(parameter-list) {statements;}
如:
Function insert(STRING, POS, INS) {
before_tmp = substr(STRING, 1, POS)
after_tmp = substr(STRING, POS + 1)
return before_tmp INS after_tmp
}
調用方法:print insert($1, 4, “XX”)
6. Awk與shell混用
因為 awk 可以作為一個 shell 命令使用, 因此 awk 能與 shell 批次程式很好的融合在一起,這給實現 awk 與 shell 程式的混合編程提供了可能。實現混合編程的關鍵是 awk 與shell script之間的對話, 換言之, 就是awk與shell script之間的資訊交流:awk從shell script中擷取所需的資訊(通常是變數的值)、在 awk 中執行 shell 命令列、shell script 將命令執行的結果送給 awk處理以及 shell script讀取 awk的執行結果等等。
6.1. awk讀取Shell script程式變數
在awk中我們可以通過“’$變數名’”的方式讀取sell scrpit程式中的變數。
例如:讀取shell scrpit程式中的變數name
下面給出兩種方式:
第一種比較常用的方式:(雙引號和單引號的意義需要明確)
#!/bin/sh
name=’John’
awk ‘{print $1,$2,”‘$name’”}’ myfile
————————————————-
第二種方式:
#!/bin/sh
name=’John’
awk ‘{print $1,$2,myname}’ myname=$name myfile
不過這種方式中,awk自訂變數myname不能在BEGIN中使用。
6.2. 將shell命令的執行結果送給awk處理
作為資訊傳送的一種方法,我們可以將一條shell命令的結果通過管道線(|)傳遞給awk處理:
例:樣本awk處理shell命令的執行結果
$who -u | awk ‘{printf(“%s正在執行%s\n”,$2,$1)}’
6.3. shell script程式讀awk的執行結果
shell中可以將awk執行結果賦值給shell變數。我們可以用變數名=`awk語句`的形式將awk執行的結果存放入一個shell script變數。當然也可以用管道線的方法將awk執行結果傳遞給shell script程式處理。
例如:找出myfile中帶有fail字串的行並統計行數,最後列印出格式為:there are (行數) lines
#!/bin/sh
temp=`awk ‘/fail/{print $0}’ myfile |wc -l`
echo “there are $temp lines
7. 參考資料
(1) http://fanqiang.chinaunix.net/program/other/2005-09-07/3621.shtml
(2) 《Unix awk使用手冊》,作者:莫名 發表時間:2002/01/27 01:39pm
(3) 書籍《sed 與 awk》修訂第三版
原創文章,轉載請註明: 轉載自董的部落格
本文連結地址: http://dongxicheng.org/script/awk-usage/