Awk的簡單用法1-1


Awk的簡單用法

下面沒有講述a w k的全部特性,也不涉及a w k的深層次編程,僅講述使用a w k執行行操作及怎樣從文本文件和字符串中抽取信息。

QUOTE:

內容有:
"
抽取域。
"
匹配正則表達式。
"
比較域。
"
a w k傳遞參數。
"
基本的a w k行操作和腳本。


a w k
語言的最基本功能是在文件或字符串中基於指定規則瀏覽和抽取信息。a w k抽取信息後,才能進行其他文本操作。完整的a w k腳本通常用來格式化文本文件中的信息。

1
調用awk

有三種方式調用a w k,第一種是命令行方式,如:

[Copy to clipboard] [ - ]

CODE:

awk [-F fild-separator] 'commands' input-file(s)


這裏,c o m m a n d s是真正的a w k命令。
上面例子中, [ - F域分隔符]是可選的,因爲a w k使用空格作爲缺省的域分隔符,因此如果要瀏覽域間有空格的文本,不必指定這個選項,但如果要瀏覽諸如p a s s w d文件,此文件各域以冒號作爲分隔符,則必須指明- F選項,如:

[Copy to clipboard] [ - ]

CODE:

awk -F:  'commands' input-file(s)


第二種方法是將所有a w k命令插入一個文件,並使a w k程序可執行,然後用a w k命令解釋器作爲腳本的首行,以便通過鍵入腳本名稱來調用它。

第三種方式是將所有的a w k命令插入一個單獨文件,然後調用:

[Copy to clipboard] [ - ]

CODE:

awk -f awk-script-file input-files(s)


- f
選項指明在文件a w k _ s c r i p t _ f i l e中的a w k腳本, i n p u t _ f i l e ( s )是使用a w k進行瀏覽的文件名。

2 awk
腳本
在命令中調用a w k時,a w k腳本由各種操作和模式組成。
如果設置了- F選項,則a w k每次讀一條記錄或一行,並使用指定的分隔符分隔指定域,但如果未設置- F選項,a w k假定空格爲域分隔符,並保持這個設置直到發現一新行。當新行出現時,a w k命令獲悉已讀完整條記錄,然後在下一個記錄啓動讀命令,這個讀進程將持續到文件尾或文件不再存在。

參照表,a w k每次在文件中讀一行,找到域分隔符(這裏是符號#),設置其爲域n,直至一新行(這裏是缺省記錄分隔符),然後,劃分這一行作爲一條記錄,接着a w k再次啓動下一行讀進程。
awk
讀文件記錄的方式

QUOTE:

1                         分隔符        2                分隔符        3        分隔符        4及換行
P. B u n n y (
記錄1 )         #         0 2 / 9 9         #         4 8         #         Yellow \n
J . Tr o l l (
記錄2 )         #         0 7 / 9 9         #         4 8 4 2 #         Brown-3 \n


2.1
模式和動作
任何a w k語句都由模式和動作組成。在一個a w k腳本中可能有許多語句。模式部分決定動作語句何時觸發及觸發事件。處理即對數據進行的操作。如果省略模式部分,動作將時刻保持執行狀態。
模式可以是任何條件語句或複合語句或正則表達式。模式包括兩個特殊字段B E G I NE N D。使用B E G I N語句設置計數和打印頭。B E G I N語句使用在任何文本瀏覽動作之前,之後文本瀏覽動作依據輸入文件開始執行。E N D語句用來在a w k完成文本瀏覽動作後打印輸出文本總數和結尾狀態標誌。如果不特別指明模式, a w k總是匹配或打印行數。
實際動作在大括號{ }內指明。動作大多數用來打印,但是還有些更長的代碼諸如i f和循環(l o o p i n g)語句及循環退出結構。如果不指明採取動作, a w k將打印出所有瀏覽出來的記錄。


2. 域和記錄
a w k
執行時,其瀏覽域標記爲$ 1$ 2 . . . $ n。這種方法稱爲域標識。使用這些域標識將更容易對域進行進一步處理。
使用$ 1 , $ 3表示參照第1和第3域,注意這裏用逗號做域分隔。如果希望打印一個有5個域的記錄的所有域,不必指明$ 1 , $ 2 , $ 3 , $ 4 , $ 5,可使用$ 0,意即所有域。Aw k瀏覽時,到達一新行,即假定到達包含域的記錄末尾,然後執行新記錄下一行的讀動作,並重新設置域分隔。
注意執行時不要混淆符號$s h e l l提示符$,它們是不同的。
爲打印一個域或所有域,使用p r i n t命令。這是一個a w k動作(動作語法用圓括號括起來)。


1.
抽取域
真正執行前看幾個例子,現有一文本文件g r a d e . t x t,記錄了一個稱爲柔道數據庫的行信息。

[Copy to clipboard] [ - ]

CODE:

$ cat grade.txt
M.Tans 5/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26
P.Bunny 02/99 48 Yellow 12 35 28
J.Troll 07/99 4842 Brown-3 12 26 26
L.Tansl 05/99   4712 Brown-2 12 30 28


此文本文件有7個域,即(1)名字、(2)升段日期、(3)學生序號、(4)腰帶級別、(5)年齡、(6)目前比賽積分、(7)比賽最高分。
因爲域間使用空格作爲域分隔符,故不必用- F選項劃分域,現瀏覽文件並導出一些數據。在例子中爲了利於顯示,將空格加寬使各域看得更清晰。

2.
保存a w k輸出
有兩種方式保存s h e l l提示符下a w k腳本的輸出。最簡單的方式是使用輸出重定向符號>文件名,下面的例子重定向輸出到文件w o w

[Copy to clipboard] [ - ]

CODE:

$ awk '{print $0}' grade.txt >wow
$ cat grade.txt


使用這種方法要注意,顯示屏上不會顯示輸出結果。因爲它直接輸出到文件。只有在保證輸出結果正確時纔會使用這種方法。它也會重寫硬盤上同名數據。

第二種方法是使用t e e命令,在輸出到文件的同時輸出到屏幕。在測試輸出結果正確與否時多使用這種方法。例如輸出重定向到文件d e l e t e _ m e _ a n d _ d i e,同時輸出到屏幕。使用這種方法,在a w k命令結尾寫入| tee delete_me_and_die

[Copy to clipboard] [ - ]

CODE:

$ awk '{print $0}' grade.txt | tee delete_me_and_die


3.
使用標準輸入
在深入講解這一章之前,先對a w k腳本的輸入方法簡要介紹一下。實際上任何腳本都是從標準輸入中接受輸入的。爲運行本章腳本,使用a w k腳本輸入文件格式,例如:

QUOTE:

belts.awk grade_student.txt
也可替代使用下述格式:
使用重定向方法:
belts.awk < grade2.txt
或管道方法:
grade2.txt | belts.awk



4.
打印所有記錄

[Copy to clipboard] [ - ]

CODE:

$ awk '{print $0}' grade.txt


a w k
讀每一條記錄。因爲沒有模式部分,只有動作部分{print $0}(打印所有記錄),這個動作必須用花括號括起來。上述命令打印整個文件。

5.
打印單獨記錄
假定只打印學生名字和腰帶級別,通過查看域所在列,可知爲f i e l d - 1f i e l d - 4,因此可以使用$ 1$ 4,但不要忘了加逗號以分隔域。

[Copy to clipboard] [ - ]

CODE:

$ awk '{print $1,$4}' grade.txt
M.Tans Green
J.Lulu green
P.Bunny Yellow
J.Troll Brown-3
L.Tansl Brown-2


6.
打印報告頭
上述命令輸出在名字和腰帶級別之間用一些空格使之更容易劃分,也可以在域間使用t a b鍵加以劃分。爲加入t a b鍵,使用t a b鍵速記引用符\ t,後面將對速記引用加以詳細討論。也可以爲輸出文本加入信息頭。本例中加入n a m eb e l t及下劃線。下劃線使用\ n,強迫啓動新行,並在\ n下一行啓動打印文本操作。打印信息頭放置在B E G I N模式部分,因爲打印信息頭被界定爲一個動作,必須用大括號括起來。在a w k查看第一條記錄前,信息頭被打印。

[Copy to clipboard] [ - ]

CODE:

$ awk 'BEGIN {print "Name Belt\n-----------------------------------"}{print $1"\t",$4}' grade.txt
Name Belt
-----------------------------------
M.Tans   Green
J.Lulu   green
P.Bunny  Yellow
J.Troll  Brown-3
L.Tansl  Brown-2


7.
打印信息尾
如果在末行加入end of report信息,可使用E N D語句。E N D語句在所有文本處理動作執行完之後才被執行。E N D語句在腳本中的位置放置在主要動作之後。下面簡單打印頭信息並告之查詢動作完成。

[Copy to clipboard] [ - ]

CODE:

$ awk 'BEGIN {print "Name\n--------"}{print $1} END {print "end-of-report"}' grade.txt
Name
--------
M.Tans
J.Lulu
P.Bunny
J.Troll
L.Tansl


8. awk
錯誤信息提示
幾乎可以肯定,在使用a w k時,將會在命令中碰到一些錯誤。a w k將試圖打印錯誤行,但由於大部分命令都只在一行,因此幫助不大。
系統給出的顯示錯誤信息提示可讀性不好。使用上述例子,如果丟了一個雙引號, a w k將返回:

[Copy to clipboard] [ - ]

CODE:

$ awk 'BEGIN {print "Name\n--------}{print $1} END {"end-of-report"}' grade.txt
awk: cmd. line:1: BEGIN {print "Name\n--------}{print $1} END {"end-of-report"}
awk: cmd. line:1:                                                            ^ unterminated string


當第一次使用a w k時,可能被錯誤信息攪得不知所措,但通過長時間和不斷的學習,可總結出以下規則。在碰到a w k錯誤時,可相應查找:

QUOTE:

" 確保整個a w k命令用單引號括起來。
"
確保命令內所有引號成對出現。
"
確保用花括號括起動作語句,用圓括號括起條件語句。
"
可能忘記使用花括號,也許你認爲沒有必要,但a w k不這樣認爲,將按之解釋語法



如果查詢文件不存在,將得到下述錯誤信息:

[Copy to clipboard] [ - ]

CODE:

$ awk 'END {print NR}' grades.txt
awk: cmd. line:2: fatal: cannot open file `grades.txt' for reading (
沒有那個文件或目錄)


9.awk
鍵盤輸入
如果在命令行並沒有輸入文件g r a d e . t x t,將會怎樣?

[Copy to clipboard] [ - ]

CODE:

$ awk 'BEGIN {print "Name\n--------"}{print $1} END {"end-of-report"}'
Name
--------


B E G I N
部分打印了文件頭,但a w k最終停止操作並等待,並沒有返回s h e l l提示符。這是因爲a w k期望獲得鍵盤輸入。因爲沒有給出輸入文件, a w k假定下面將會給出。如果願意,順序輸入相關文本,並在輸入完成後敲<Ct r l - D >鍵。如果敲入了正確的域分隔符, a w k會像第一個例子一樣正常處理文本。這種處理並不常用,因爲它大多應用於大量的打印稿。


2.3awk
中正則表達式及其操作

g r e p一章中,有許多例子用到正則表達式,這裏將不使用同樣的例子,但可以使用條件操作講述a w k中正則表達式的用法。
這裏正則表達式用斜線括起來。例如,在文本文件中查詢字符串G r e e n,使用/ G r e e n /可以查出單詞G r e e n的出現情況。

2.4
元字符
這裏是a w k中正則表達式匹配操作中經常用到的字符,詳細情況請參閱本書第7章正則表達式概述。

[Copy to clipboard] [ - ]

CODE:

\ ^ $ . [] | () * + ?


這裏有兩個字符第7章沒有講到,因爲它們只適用於a w k而不適用於g r e ps e d。它們是:

QUOTE:

+ 使用+匹配一個或多個字符。
匹配模式出現頻率。例如使用/X Y?Z/匹配X Y ZY Z

 

 

條件操作符
a w k
條件操作符
操作符描述操作符描述
<
小於> = 大於等於
< =
小於等於~ 匹配正則表達式
= =
等於!~ 不匹配正則表達式
!=
不等於

1.
匹配
爲使一域號匹配正則表達式,使用符號後緊跟正則表達式,也可以用i f語句。a w ki f後面的條件用()括起來。
觀察文件g r a d e . t x t,如果只要顯示b r o w n腰帶級別可知其所在域爲f i e l d - 4,這樣可以寫出表達式{if($4~/brown/) print }意即如果f i e l d - 4包含b r o w n,打印它。如果條件滿足,則打印匹配記錄行。可以編寫下面腳本,因爲這是一個動作,必須用花括號{ }括起來。

[Copy to clipboard] [ - ]

CODE:

[root@Linux_chenwy sam]# awk '{if($4~/Brown/) print $0}' grade.txt
J.Troll 07/99 4842 Brown-3 12 26 26
L.Tansl 05/99 4712 Brown-2 12 30 28


匹配記錄找到時,如果不特別聲明, a w k缺省打印整條記錄。使用i f語句開始有點難,但不要着急,因爲有許多方法可以跳過它,並仍保持同樣結果。下面例子意即如果記錄包含模式b r o w n,就打印它:

[Copy to clipboard] [ - ]

CODE:

[root@Linux_chenwy sam]# awk '$0 ~ /Brown/' grade.txt
J.Troll 07/99 4842 Brown-3 12 26 26
L.Tansl 05/99 4712 Brown-2 12 30 28


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章