awk的模式和動作
【文法結構】
awk -F 'Pattern1{Action1};Pattern2{Action2}' input-file或
awk -F '{Action}' input-file
① -F 為字段分隔符。若不指定,預設會使用空格作為分隔符。
② /Pattern/和{Action}需要用單引号引起來,防止shell作解釋。
③ /Pattern/是可選的。如果不指定,awk 将處理輸入檔案中的所有記錄。如果指定一個模式,awk 則隻處理比對指定的模式的記錄。
④ {Action} 為 awk 指令,可以是單個指令,也可以多個指令。整個 Action(包括裡面的所有指令)都必須放在{ 和 }之間。
⑤ Input-file 要處理的目标檔案
⑥ Action必須被{}包裹,沒有被{}包裹的就是Pattern
【Pattern】
awk 可接受許多不同型态的 Pattern. 一般常使用 "關系表達式"(Relational expression) 來當成 Pattern。awk 通過判斷 Pattern 的值來決定是否執行其後所對應的Actions。以下是幾種常見的Pattern:
BEGIN
BEGIN 為 awk 的保留字, 是一種特殊的 Pattern.
BEGIN 成立(值為true)的時候是: "awk 程式一開始執行, 尚未讀取任何資料之前." 是以在 BEGIN { Actions } 文法中, 其 Actions 部份僅于程式一開始執行時被執行一次. 當 awk 從資料檔案讀入資料行後, BEGIN 便不再成立, 故不論有多少資料行, 該 Actions 部份僅被執行一次.一般常把 "與資料檔案内容無關" 與 "隻需執行ㄧ次" 的部分置于該Actions(以 BEGIN 為 Pattern)中.
例如:
BEGIN {
FS = "[ \t:]" # 于程式一開始時, 改變awk切割字段的方式
RS = "" # 于程式一開始時, 改變awk分隔資料行的方式
count = 100 # 設定變量 count 的起始值
print " This is a title line " # 印出一行 title
}
....... # 其它 Pattern { Actions } .....
有些awk程式甚至"不需要讀入任何資料行". 遇到這情況可把整個程式置于以 BEGIN 為 Pattern的 Actions 中.
例如 :
BEGIN { print " Hello ! the Word ! " }
注意 :執行該類僅含 BEGIN { Actions } 的程式時, awk 并不會開啟任何資料檔案進行處理.
END
END 為 awk 的保留字, 是另一種特殊的 Pattern.
END 成立(其值為true)的時機與 BEGIN 恰好相反, 為:"awk 處理完所有資料, 即将離開程式時"平常讀入資料行時, END并不成立, 故其對應的 Actions 并不被執行; 唯有當awk讀完所有資料時, 該 Actions 才會被執行
注意 : 不管資料行有多少, 該 Actions 僅被執行一次.
關系表達式
使用像 " A 關系運算符 B" 的表達式當成 Pattern.
當 A 與 B 存在所指定的關系(Relation)時, 該 Pattern 就算成立(true).
length($0) <= 80 { print $0 }
上式中 length($0)<= 80 是一個 Pattern, 當 $0(資料行)之長度小于等于80時該 Pattern 之值為true, 将執行其後的 Action (列印該資料行).
awk 中提供下列 關系運算符(Relation Operator)
運算符 含意
> 大于
< 小于
>= 大于或等于
<= 小于或等于
== 等于
!= 不等于
~ match
!~ not match
上列關系運算符除~(match)與!~(not match)外與 C 語言中之含意一緻.
~(match) 與!~(match) 在 awk 之含意簡述如下 :
若 A 為一字元串, B 為一正規表達式.
A ~B 判斷 字元串A 中是否 包含 能比對(match)B式樣的子字元串.
A !~B 判斷 字元串A 中是否 未包含 能比對(match)B式樣的子字元串.
$0 ~ /program[0-9]+\.c/ { print $0 }
$0 ~ /program[0-9]+\.c/ 整個是一個 Pattern, 用來判斷$0(資料行)中是否含有可 match /program[0-9]+\.c/ 的子字元串, 若$0 中含有該類字元串, 則執行 print (列印該行資料).
Pattern 中被用來比對的字元串為$0 時(如本例), 可僅以正規表達式部分表示整個Pattern.故本例的 Pattern 部分$0 ~/program[0-9]+\.c/ 可僅用/program[0-9]+\.c/表之
常量
常量有兩種類型,字元串常量和數值常量.字元串常量必須用引号括起來,數值常量不需要,如數值0和字元串"0"是不一樣的.
數值常量中,0代表假,非0的數值常量代表真
字元串常量中,空字元串為假,非空字元串為真
例如
1{print}
上式利用數值常量1作為一個邏輯值.
該式中數值常量為1非0為真
空Pattern
如果awk的語句中省略了pattern,即pattern為空,則代表永遠為真,并執行後面緊跟的action.如果action省略則預設action為print
{name=1}5
上式還原完整的格式為 空pattern {name=1}5 {print}.
正規表達式
直接使用正規表達式當成 Pattern; 此為 $0 ~ 正規表達式 的簡寫.
該 Pattern 用以判斷 $0(資料行) 中是否含有比對該正規表達式的子字元串; 若含有則成立(true) 執行其對應的 Actions.
/^[0-9]*$/ { print "This line is a integer !" }
與 $0 ~/^[0-9]*$/ { print "This line is a integer !" } 相同
混合 Pattern
之前所介紹的各種 Patterns, 其計算後結果為一邏輯值(True or False).awk 中邏輯值彼此間可通過&&(and), ||(or), !(not) 結合成一個新的邏輯值.故不同 Patterns 彼此可通過上述結合符号來結合成一個新的 Pattern. 如此可進行複雜的條件判斷.
例 如 :
FNR >= 23 && FNR <= 28 { print " " $0 }
上式利用&& (and) 将兩個 Pattern 求值的結果合并成一個邏輯值.
該式将資料檔案中 第23行 到 28行 向右移5格(先輸出5個空白字元)後輸出.
/2/0{print}
上式利用正規表達式和數值常量0結合的結果合并為一個邏輯值.
該式中非空字元串永遠為真,不管正則結果是真還是假,結果永遠為真,列印檔案所有行,等同于1{print}簡寫為{print}
Pattern1 , Pattern2
遇到這種 Pattern, awk 會設定一個區間的開關,即switch(或flag).
當awk讀入的資料行使得 Pattern1 成立時, awk 會打開(turn on)這 switch.
當awk讀入的資料行使得 Pattern2 成立時, awk 會關上(turn off)這個 switch.
該 Pattern 成立的條件是 :
當這個 switch 被打開(turn on)時 (包括 Pattern1, 或 Pattern2 為真的情況)
可改寫為
FNR == 23 , FNR == 28 { print " " $0 }
說 明 :
當 FNR >= 23 時, awk 就 turn on 這個 switch; 因為随着資料行的讀入, awk不停的累加 FNR. 當 FNR = 28 時, Pattern2 (FNR == 28) 便成立, 這時 awk 會關閉 switch.
當 switch 打開的期間, awk 會執行 print " " $0
'/2/,/2/
其實等價于
/2/
說明:
當目前讀入的行即$0中比對到2這個字元,awk就turn on這個switch;從目前讀入的行開始繼續向下讀,直到讀入的行中比對到2這個字元,awk就turn off這個switch.
'/1/,/2/
當目前讀入的行比對到1這個字元,awk就turn on這個switch,從目前讀入的行開始繼續向下讀,直到讀入的行比對到2這個字元,awk就turn off這個switch.
【Actions】
Actions 是由下列指令(statement)所組成 :
· 表達式 ( function calls, assignments..)
· print 表達式清單
· printf( 格式化字元串, 表達式清單)
· if( 表達式 ) 語句 [else 語句]
· while( 表達式 ) 語句
· do 語句 while( 表達式)
· for( 表達式; 表達式; 表達式) 語句
· for( variable in array) 語句
· delete
· break
· continue
· next
· exit [表達式]