本文轉自chinaunix http://bbs.chinaunix.net/thread-4246512-1-1.html 做者reyleonhtml
咱們知道, awk程序由一系列 pattern 以及與之對應的 action 組成的 rule 組成,rule之間用";"分號隔開, 一條輸入記錄與 pattern 匹配則執行與之關聯的action, 以下所示:
awk '
pattern { action };
pattern { action };
.....
'
但是, 不少人並不清楚什麼東西能夠作爲 pattern下面就來聊聊這些個事兒. 如下文本作爲測試文本:正則表達式
1 $ cat myfile 2 Amelia 555-5553 amelia.zodiacusque@gmail.com F 3 Anthony 555-3412 anthony.asserturo@hotmail.com A 4 Becky 555-7685 becky.algebrarum@gmail.com A 5 Bill 555-1675 bill.drowning@hotmail.com A 6 Broderick 555-0542 broderick.aliquotiens@yahoo.com R 7 Camilla 555-2912 camilla.infusarum@skynet.be R 8 Fabius 555-1234 fabius.undevicesimus@ucb.edu F 9 Julie 555-6699 julie.perscrutabor@skeeve.com F 10 Martin 555-6480 martin.codicibus@hotmail.com A 11 Samuel 555-3430 samuel.lanceolis@shu.edu A 12 Jean-Paul 555-2127 jeanpaul.campanorum@nyu.edu R
首先, 要記住, 凡是被 {} 包裹的, 就是 action, 或者說, action 必然被 {} 包裹着
凡是沒有被{}包裹的, 就是pattern, 或者說pattern不能被{}包裹着.
一. 正則表達式作爲 pattern
最多見的, 就是一個正則表達式作爲一個 pattern了, 如:
測試
1 awk '/555-5553/ { print $0 }' myfile
/555-5553/ 就是一個正則表達式, 若是輸入記錄匹配555-5553, 就輸出這條記錄, 這裏只有第一行匹配 555-5553, 因此就輸出了第一行這條記錄.ui
1 $ awk '/555-5553/ { print $0 }' myfile 2 Amelia 555-5553 amelia.zodiacusque@gmail.com F
二. 比較表達式作爲 patternspa
1 $ awk '$NF == "A" { print $0 }' myfile 2 Anthony 555-3412 anthony.asserturo@hotmail.com A 3 Becky 555-7685 becky.algebrarum@gmail.com A 4 Bill 555-1675 bill.drowning@hotmail.com A 5 Martin 555-6480 martin.codicibus@hotmail.com A
最後一個字段爲 "A" 的, 輸出這條記錄..net
1 $ awk '$NF != "A" { print $0 }' myfile 2 Amelia 555-5553 amelia.zodiacusque@gmail.com F 3 Broderick 555-0542 broderick.aliquotiens@yahoo.com R 4 Camilla 555-2912 camilla.infusarum@skynet.be R 5 Fabius 555-1234 fabius.undevicesimus@ucb.edu F 6 Julie 555-6699 julie.perscrutabor@skeeve.com F 7 Jean-Paul 555-2127 jeanpaul.campanorum@nyu.edu R
最後一個字段不爲 "A" 的, 輸出這條記錄.
三. 常量表達式作爲 pattern
這種pattern通常是最不易被新手理解的, 事實上, 既然是 pattern 匹配, 結果就只有兩種狀況, 要麼匹配(即爲真),就執行後面的 action, 要麼不匹配(即爲假), 就不會執行後面的action.
因此, awk 的規則基本上也就是:
awk ' 真 { 執行代碼 }; 假 { 不執行代碼 }'
也理解爲:
awk ' 條件 { 動做 } 條件 { 動做 } '
什麼東西能夠作爲一個常量? 一個數字, 或者一個字符串, 均可以作爲一個常量 pattern. 那這裏就有一個龜腚了:
凡是非0的數字, 就表示pattern匹配成功, 也就是pattern爲真. 不然表示匹配失敗, 爲假.
凡是非空的字符串, 就表示pattern匹配成功, 也就是pattern爲真. 不然表示匹配失敗, 爲假.
注意: 字符串是由引號引發來的! 好比數字 0 與 字符串 "0" 不是同樣的. 數字0爲假, 字符串"0"爲真(不爲空).
如:unix
1 $ awk '1 { print $0 }' myfile 2 Amelia 555-5553 amelia.zodiacusque@gmail.com F 3 Anthony 555-3412 anthony.asserturo@hotmail.com A 4 Becky 555-7685 becky.algebrarum@gmail.com A 5 Bill 555-1675 bill.drowning@hotmail.com A 6 Broderick 555-0542 broderick.aliquotiens@yahoo.com R 7 Camilla 555-2912 camilla.infusarum@skynet.be R 8 Fabius 555-1234 fabius.undevicesimus@ucb.edu F 9 Julie 555-6699 julie.perscrutabor@skeeve.com F 10 Martin 555-6480 martin.codicibus@hotmail.com A 11 Samuel 555-3430 samuel.lanceolis@shu.edu A 12 Jean-Paul 555-2127 jeanpaul.campanorum@nyu.edu R
1 $ awk '2 { print $0 }' myfile 2 Amelia 555-5553 amelia.zodiacusque@gmail.com F 3 Anthony 555-3412 anthony.asserturo@hotmail.com A 4 Becky 555-7685 becky.algebrarum@gmail.com A 5 Bill 555-1675 bill.drowning@hotmail.com A 6 Broderick 555-0542 broderick.aliquotiens@yahoo.com R 7 Camilla 555-2912 camilla.infusarum@skynet.be R 8 Fabius 555-1234 fabius.undevicesimus@ucb.edu F 9 Julie 555-6699 julie.perscrutabor@skeeve.com F 10 Martin 555-6480 martin.codicibus@hotmail.com A 11 Samuel 555-3430 samuel.lanceolis@shu.edu A 12 Jean-Paul 555-2127 jeanpaul.campanorum@nyu.edu R
1 $ awk '0 { print $0 }' myfile 2 // 數字 0 作爲 pattern, 0爲假, pattern 匹配失敗, 因此不執行 print $0, 沒有打印.
1 $ awk ' "0" { print $0 }' myfile 2 Amelia 555-5553 amelia.zodiacusque@gmail.com F 3 Anthony 555-3412 anthony.asserturo@hotmail.com A 4 Becky 555-7685 becky.algebrarum@gmail.com A 5 Bill 555-1675 bill.drowning@hotmail.com A 6 Broderick 555-0542 broderick.aliquotiens@yahoo.com R 7 Camilla 555-2912 camilla.infusarum@skynet.be R 8 Fabius 555-1234 fabius.undevicesimus@ucb.edu F 9 Julie 555-6699 julie.perscrutabor@skeeve.com F 10 Martin 555-6480 martin.codicibus@hotmail.com A 11 Samuel 555-3430 samuel.lanceolis@shu.edu A 12 Jean-Paul 555-2127 jeanpaul.campanorum@nyu.edu R 13 // 字符串 "0" 作爲 pattern, 爲真, pattern 匹配成功, 因此執行 print $0, 打印.
還有一些, 多是寫錯的賦值語句作爲了pattern的, 或者其餘亂七八糟的, 等等..:code
1 $ awk 'a=0' myfile // 數字0. 假, 沒輸出.
1 $ awk 'a=1' myfile // 1 爲真. 2 Amelia 555-5553 amelia.zodiacusque@gmail.com F 3 Anthony 555-3412 anthony.asserturo@hotmail.com A 4 Becky 555-7685 becky.algebrarum@gmail.com A 5 Bill 555-1675 bill.drowning@hotmail.com A 6 Broderick 555-0542 broderick.aliquotiens@yahoo.com R 7 Camilla 555-2912 camilla.infusarum@skynet.be R 8 Fabius 555-1234 fabius.undevicesimus@ucb.edu F 9 Julie 555-6699 julie.perscrutabor@skeeve.com F 10 Martin 555-6480 martin.codicibus@hotmail.com A 11 Samuel 555-3430 samuel.lanceolis@shu.edu A 12 Jean-Paul 555-2127 jeanpaul.campanorum@nyu.edu R
1 $ awk 'x-1' myfile // x 爲未定義的變量, 作數學運算, 結果爲 -1 , 因 -1 也是非0的數字常量, pattern 匹配成功, 爲真, print $0. 2 Amelia 555-5553 amelia.zodiacusque@gmail.com F 3 Anthony 555-3412 anthony.asserturo@hotmail.com A 4 Becky 555-7685 becky.algebrarum@gmail.com A 5 Bill 555-1675 bill.drowning@hotmail.com A 6 Broderick 555-0542 broderick.aliquotiens@yahoo.com R 7 Camilla 555-2912 camilla.infusarum@skynet.be R 8 Fabius 555-1234 fabius.undevicesimus@ucb.edu F 9 Julie 555-6699 julie.perscrutabor@skeeve.com F 10 Martin 555-6480 martin.codicibus@hotmail.com A 11 Samuel 555-3430 samuel.lanceolis@shu.edu A 12 Jean-Paul 555-2127 jeanpaul.campanorum@nyu.edu R
1 1 $ awk 'xxoo' myfile //xxoo爲變量, 未賦值, 爲假
1 $ awk '"xxoo"' myfile // 字符串, 真. 2 Amelia 555-5553 amelia.zodiacusque@gmail.com F 3 Anthony 555-3412 anthony.asserturo@hotmail.com A 4 Becky 555-7685 becky.algebrarum@gmail.com A 5 Bill 555-1675 bill.drowning@hotmail.com A 6 Broderick 555-0542 broderick.aliquotiens@yahoo.com R 7 Camilla 555-2912 camilla.infusarum@skynet.be R 8 Fabius 555-1234 fabius.undevicesimus@ucb.edu F 9 Julie 555-6699 julie.perscrutabor@skeeve.com F 10 Martin 555-6480 martin.codicibus@hotmail.com A 11 Samuel 555-3430 samuel.lanceolis@shu.edu A 12 Jean-Paul 555-2127 jeanpaul.campanorum@nyu.edu R
四. 空 patternhtm
1 $ awk '{print $0}' myfile 2 Amelia 555-5553 amelia.zodiacusque@gmail.com F 3 Anthony 555-3412 anthony.asserturo@hotmail.com A 4 Becky 555-7685 becky.algebrarum@gmail.com A 5 Bill 555-1675 bill.drowning@hotmail.com A 6 Broderick 555-0542 broderick.aliquotiens@yahoo.com R 7 Camilla 555-2912 camilla.infusarum@skynet.be R 8 Fabius 555-1234 fabius.undevicesimus@ucb.edu F 9 Julie 555-6699 julie.perscrutabor@skeeve.com F 10 Martin 555-6480 martin.codicibus@hotmail.com A 11 Samuel 555-3430 samuel.lanceolis@shu.edu A 12 Jean-Paul 555-2127 jeanpaul.campanorum@nyu.edu R
// 這裏沒有 pattern, 空的, empty pattern, 那麼就表示匹配輸入記錄永遠成功, 也就是說永遠爲真, 這是龜腚. action永遠都會執行.
咱們知道, awk 的rule 就是由一系列 pattern 和 action 構成, 這裏所謂的空 pattern, 也能夠說是省略了 pattern, 那麼 action 可不能夠省略呢?
事實上, action也是能夠省略的, 但若是省略了的話,它就會有一個默認的action行爲, 即 { print $0 } !
不少人新手常常搞不懂一下的代碼:
awk '{a=1}1' myfile
常常會碰到有人問, 這個代碼後面的1是幹嗎的? 其實, 咱們拆分下 awk 的 rule 就明白了.
awk '{a=1}1' 這個語句包含了兩條規則:
awk '
[空pattern] {a=1} #第一條規則
1 [{省略的action}] #第二條規則
'
第一條rule: {a=1} , 這條規則這裏有一個{}大括號包裹着, 表示這是一個 action, 可是省略了pattern, 即空pattern,
上面說了, 空pattern是永遠匹配爲真的,
因此{a=1}這個action會針對每條輸入記錄對執行,只是咱們看不到它的具體表現而已.
第二條rule: 1, 這條規則僅僅只有一個1字, 沒有被{}大括號包裹着,
因此這個1是一個pattern, 省略了{action}, 而這個數字 1 , 實際上就是一個常量表達式pattern, 因它爲非0的數字,因此pattern匹配成功,爲真,就執行action,
由於這裏省略了{action},就觸發默認的行爲,而默認的action行爲是print $0,即打印這條記錄.
再如: awk '1;1' ,省略了兩個action, 因此這條實際上就是兩個 {print $0}{print $0}.
因此, 凡是action只是要輸出這條記錄的, 統統均可以省略這個 action.
如:blog
1 $ awk '/Amelia/ || /Martin/' myfile 2 Amelia 555-5553 amelia.zodiacusque@gmail.com F 3 Martin 555-6480 martin.codicibus@hotmail.com A 4 $ awk '$NF ~ /F/' myfile 5 Amelia 555-5553 amelia.zodiacusque@gmail.com F 6 Fabius 555-1234 fabius.undevicesimus@ucb.edu F 7 Julie 555-6699 julie.perscrutabor@skeeve.com F 8 $ awk 'NR==5' myfile 9 Broderick 555-0542 broderick.aliquotiens@yahoo.com R
五. 特殊的 pattern: BEGIN, END ..
在 awk 中, 確定會常常看到 BEGIN, END 這兩個玩意兒. 如 awk 'BEGIN { ... } END { ... } '
實際上, BEGIN 和 END 只是兩個特殊的 pattern . 相似的還有 BEGINFILE, ENDFILE.
BEGIN 在讀入文件以前匹配成功, 即爲在讀入文件以前這條 rule 就已經執行了.
END 在處理完文件以後才匹配陳宮, 即在處理完文件以後纔會執行這條 rule.
1 $ awk 'BEGIN { n=5 } NR==n { print $0 } END { print $0 }' myfile 2 Broderick 555-0542 broderick.aliquotiens@yahoo.com R 3 Jean-Paul 555-2127 jeanpaul.campanorum@nyu.edu R
分析下這條 awk 語句:
首先, 它包含三條規則
1. BEGIN { n=5 } ,BEGIN 爲 特殊pattern, {n=5} 爲 action
2. NR==n { print $0 }, NR==n 是一個比較表達式pattern, { print $0 } 爲action.
3. END { print $0 }, END 也是一個特殊的pattern.
BEGIN 模式通常讀入文件以前經常使用的是作一些相關的定義操做, 這裏設定變量n=5.
而後awk開始處理記錄, 當 NR==n 時, 即處理到咱們定義的那條記錄時(第5條記錄時), 執行 print $0, 輸出這條記錄.
最後是END模式, awk處理完文件裏, END模式匹配成功,執行print $0, 即輸出最後一條記錄.
因此, 結果是輸出第5條記錄和最後一條記錄.
六. 模式範圍: begpat, endpat
這個模式範圍, 是由兩個 pattern 組成, 每一個 pattern能夠是任意的非特殊類型(非BEGIN/END模式類型)的pattern類型(能夠是正則,比較,常量等pattern).
這個模式範圍匹配的規則有點兒特殊, 這裏以一個"開閘放水"的例子作爲一個類比.
1. 首先以第一個pattern匹配輸入記錄, 若是第一個pattern匹配成功,就"打開放水的開關開始放水",[開關的狀態: 開], 即會當即執行後面的action.此時無論第二個pattern是否匹配.
2. 接着再匹配第二pattern, 若是第二pattern匹配失敗,開關的狀態不變,即仍是會執行action.
3. 接着繼續以第二個pattern匹配下一條輸入記錄,直到第二個pattern匹配成功. 就"關閉放水的開關中止放水",[開關的狀態: 關], 模式範圍匹配結束.
4. 以1,2,3步驟進入下一輪模式範圍匹配
如:
1 $ awk 'NR==4, /555-3430/ { print $0}' myfile 2 Bill 555-1675 bill.drowning@hotmail.com A 3 Broderick 555-0542 broderick.aliquotiens@yahoo.com R 4 Camilla 555-2912 camilla.infusarum@skynet.be R 5 Fabius 555-1234 fabius.undevicesimus@ucb.edu F 6 Julie 555-6699 julie.perscrutabor@skeeve.com F 7 Martin 555-6480 martin.codicibus@hotmail.com A 8 Samuel 555-3430 samuel.lanceolis@shu.edu A
先執行 NR==4 這個 pattern 匹配, 當第四條記錄匹配成功時, 放水開關打開, 開始放水了, 即開始執行action , 執行 print $0 , 輸出第四條記錄.接着使用 /555-3430/ 當前記錄, 不成功.第5條記錄繼續執行 action.繼續以第二個pattern匹配這條記錄..不成功..,開關是開的第6條記錄繼續執行 action.繼續以第二個pattern匹配這條記錄..不成功..,開關是開的.....直到匹配 /555-3430/, 第二個pattern匹配成功. 開關關閉. 模式範圍匹配結束..開始下一輪模式範圍匹配..以上就是各類 pattern 的簡要解說了.. 至於 action, 也沒啥可說的, action通常作具體的事情.那些個流程控制語句 if/for/while 等通常都屬於action了, 不能作爲 pattern了.