grep gawk
?11.2.1?grep和正則表達式?
???
??讓我們首先從grep命令開始。這個命令大家應該很熟悉了,它用來在文件中查找一個?
字符串。不過,實際上,grep的處理功能要強大和復雜的多。?
???
??grep?命令的語法是?
???
???grep?[模式]?[文件名]?
???
??如果沒有給出文件名,就缺省使用標準輸入。grep每次讀取一行,并且和給出的模式?
進行匹配,如果成功就把這一行會顯,例如:(粗體的是我們輸入的內容)?
???
??$?grep?test?
???
??close?
???
??test?my?hand?
???
??test?my?hand?
?
???
??grep的“模式”也稱為正則表達式,可以由各種基本的正則表達式元素構成。正則表?
達式元素主要包括下面幾種:?
???
??字符串??????匹配任何字符串,例如grep?test表示在標準輸入中1?
???
???[...]??????????封閉集中匹配一個字符,如:[abcde]可以匹配a,b,c,d,e?
???
??[^...]?????????求補集中匹配一個字符,例如[^ABC]匹配?
???
??.??????????????匹配任意字符?
???
??/s?????????????空白符?
???
??/S?????????????非空白符?
???
??/d?????????????數字?
???
??/D?????????????非數字?
???
??/w?????????????字母或數字?
???
??/W?????????????非字母和數字?
???
??*????????匹配任何字符?
???
??上面的形式是grep中使用的基本正則表達式,另外,還可以使用egrep,egrep是grep?
的一個擴展版本,支持下面這些擴展的正則字符串:?
???
??^??????????????匹配一行的開始?
???
??$??????????????匹配一行的結尾?
???
??(?)????????????確定正則表達式求值順序,和正常演算中的括號意思差不多。?
???
??(...|...|...)??或,可選項之一進行匹配,例如:(abc|dev|ghi)可以匹配abc,dev,gh?
i,而(ww|gg)do可以匹配wwdo或者ggdo。?
???
??+??????????????一次或多次模式?
???
?????????????????如:aba+匹配aba,abaa...不匹配ab?
???
??通常,我們有兩種方法使用grep和egrep,一種是使用管道,例如我們應該熟悉的ps??
ax?|grep?sendmail,另一種是直接在文件中搜索對應的字符串。?
???
??grep/egrep還可以在命令行使用開關,常用的開關包括:?
???
??-b?在行前加上塊號?
???
??-c?統計匹配行的個數?
???
??-n?在行前加上行號?
???
??-w?將模式解釋為字符串,所有正則表達式的控制命令失效?
???
??-x?精確匹配?
???
??-r?查詢文件時包含子目錄?
???
??舉個例子來說,我們想在/var/log/httpd/access_log中查詢所有不是來自本地(192?
.168.0.1)的請求記錄,可以執行:?
???
??grep?–v?"^192.168.0.1"?/var/log/httpd/access_log?
???
??^用來讓grep?只在行首匹配。?
???
??在grep查詢的時候可以使用通配符代表多個文件,例如,grep?start?*?-r將在當前目?
錄以及所有子目錄的所有文件中查詢start字符串。?
???
??11.2.2?gawk的使用方法?
???
??gawk是awk的一個實現,awk是一種用來處理報告等文本文件的腳本語言。不過,我們?
介紹這個產品的主要目標是用它來處理各種程序的記賬文件。對于復雜的腳本,還是用?
Perl比較合適。?
???
??gawk?的主要功能是針對檔案的每一行搜尋指定的?模式。,每當找到一個匹配的模式?
,gawk就會去執行你設定的動作。按照這個方式,?gawk?依此方式處理輸入檔案的每一?
行直到輸入檔案結束。如果對于某個模式沒有設置對應的動作,gawk將直接將這個行顯?
示出來。?
???
??為了使用gawk,你通常必須先寫一個awk腳本,除非模式/動作非常簡單,可以在一行?
上完成。我們用一個例子來解釋gawk的基本用法,首先產生一個目錄列表文件:?
???
??ls?–l?/etc?>?list?
???
??現在list的內容有點像這樣:?
???
??total?2164?
???
??drwxr-xr-x???3?root?????root?????????4096?Feb?15?22:55?CORBA?
???
??-rw-r--r--???1?root?????root?????????2045?Sep?24??1999?DIR_COLORS?
???
??-rw-r--r--???1?root?????root???????????17?Mar?25?19:59?HOSTNAME?
???
??…………?
???
??現在我們選擇一個最簡單的例子,簡單地查找所有屬性是drwxr-xr-x的目錄文件:?
???
??gawk?'/drwxr-xr-x/?{print?$0}'?list?
???
??將輸出所有這樣的目錄。?
???
??這個例子看上去沒有什么實際用處,因為用grep也可以做同樣的動作,那么我們可以?
看一看下面這個功能:?
???
??$?gawk?'$1=="-rwxr-xr-x"??{sum=sum+$5}?END?{print?sum}'?list?
???
??15041?
???
??這個是什么意思?對于所有屬性是755的文件,讓gawk對第五欄的數字求和。第五欄我?
們可以看到就是文件的長度,因此這個命令將顯示所有屬性為755的文件的總共的長度。?
???
??$n是gawk中非常重要的概念,它用來表示文本串的分欄。缺省的情況下,gawk將輸入?
字符串(從文件中讀入的每一行)按照分割的空格分成若干個字段,每個字段作為一個?
變量,例如有一行?
???
??my?name?is?3th?test??
???
??那么,在awk讀入這一行之后,就產生了$1到$5變量,其中$1="my",$2="is",………?
,最后$5="test"。另外還有一個特殊的變量$0,它表示整個輸入行,也就是這個字符串?
"my?name?is?test"。另外還有一個特殊的變量NF,它表示當前行的字段的個數,在現在?
的情況下,NF應該等于5。?
???
??在某些特殊的情況下,你可能需要改變分割符的定義,這可以通過對FS賦值來完成,?
例如FS=","將分割符定義為都號而不是缺省的空格。?
???
??在一般情況下,gawk可以從命令文件中獲得模式/動作,命令文件的格式很簡單,就是?
直接將應該寫在命令行上的模式/動作對寫在文件里面,每個對構成一行,模式可以有兩?
種,一種是模式匹配,也就是我們在前面解釋的正則表達式,如果使用正則表達式,那?
么需要用兩個/把它們夾在一起,例如/[A-Z]/表示正則表達式[A-Z]。?
???
??另一種模式是比較指令,比較指令可以用比較操作符和邏輯運算符來構成,常用的比?
較操作符有:?
???
??==??等于??<=?不大于??~?按照正則表達式匹配?
???
??<??小于??>=?不小于??!~?按照正則表達式不匹配?
???
??>??大于??!=?不等于?
???
??邏輯運算符有?
???
??&&??和??||??或??!?非??()括號?
?
???
??設定了模式后,就可以設置對應的動作了,在gawk中,動作必須用花括號括起來。ga?
wk能完成的動作并不多,畢竟它是一種報告分析語言。一般情況下,只要熟悉print和p?
rintf命令就足夠了,print命令的格式非常簡單:?
???
??print?item1,item2,…………?
???
??輸出時,每個項目輸出一欄,中間用空格分開。一個print后面不跟著任何變量會導致?
gawk顯示當前的輸入行($0)。如果要輸出一個字符串,使用引號把它括起來,特別是?
如果要輸出一個空行,使用print?""。這里是一個例子,它將list文件的頭兩欄輸出:?
???
??????????gawk?'{print?$1,$2}'?list?
???
??由于輸入的文本文件內容有多行,你在命令欄中設計的模式/動作會對每一行執行一次?
。就是:?
???
??total?2164?
???
??drwxr-xr-x?3?
???
??-rw-r--r--?1?
???
??-rw-r--r--?1?
???
??-rw-r--r-1?
???
??…………………?
???
??如果你要精確地控制輸出,也可以使用printf命令,這個命令的格式是:?
???
?????printf?format,?item1,?item2,?...?
???
?????format參數就是C語言里面的格式控制符,例如%c,%d,%f等等。在?%?與格式控制?
字母之間可加入?modifier,modifier?是用來進一步控制輸出的格式。可能的?modifie?
r?如下所示:?
???
??'-'?????使用在?width?之前,指明是向左靠齊。如果'-'沒有出現,則會在被指定的?
寬度向右靠齊。例如:?
???
??????????printf?"%-4S",?"foo"會印出'foo?'。?
???
??'width'?這一個數字指示相對應的欄位印出時的寬度。例如:?
???
???printf?"%4s","foo"?????會印出'?foo'。?
???
??????????width?的值是一個最小寬度而非最大寬度。如果一個?item?的值需要的寬度?
比?width?大,則不受?width?的影響。例如printf?"%4s","foobar"將印出'foobar'。?
???
??'.prec'?此數字指定印出時的精確度。它指定小數點右邊的位數。如果是要印出一個?
字串,它指定此字串最多會被印出多少個字符。?
???
??作為一種腳本語言,gawk允許使用變量,定義變量非常簡單,就是直接用等號對它賦?
值。為了在gawk程序的開始處對變量賦值,gawk專門提供了BEGIN語句,這個語句將在所?
有行被讀入之前執行,而且只執行一次,通常用它來執行初始化命令,例如?
???
??BEGIN?{?sum=0;count=0;average=0.0;}?
???
??對于變量可以使用數學表達式進行運算,運算符包括常見的加減乘除算符,以及^(乘?
方),%(取余)和著名的++,--。不過注意gawk在做除法的時候總是使用浮點除法,除了?
取余算符%。?
???
??函數?
???
??另外,gawk包含下列函數:?
???
??數學函數?
???
??atan2(x,y)??????y/x的正切?
???
??cos(x)????余弦函數?
???
??sin(x)????正弦函數?
???
??int(x)????取整?
???
??log(x)????取自然對數?
???
??exp(x)????指數函數?
???
??rand(x)????生成一個0到1之間的隨機數?
???
??srand()????初始化隨機數發生器?
???
??systime()????返回從1970年1月1日0:00到當前時間的秒數?
???
??sqrt(x)????取x的平方根?
???
??字符串函數?
???
??index(string1,string2?)?
???
??????它會在string1?里面,尋找string2?第一次出現的地方,返回值是字串string2出?
現在字串string1?里面的位置。如果找不到,返回值為?0。?
???
??????例如:?
???
??????????print?index("peanut","an")?
???
??????會印出?3。?
???
??length(string)?
???
??string字符串的長度?
???
??????例如:?
???
??????????length("abcde")?
???
??????是?5。?
???
??match(string,regexp)?
???
??????match?函數會在字串?string?里面,尋找符合?regexp?的最長、最靠左邊的子字?
串。返回值是?regexp?在?string?的開始位置,即?index值。這個函數會設定內部變量?
?RSTART?等於?index,內部變量RLENGTH?等於符合的子串個數。如果不符合,則會設定?
?RSTART?為0、RLENGTH?為?-1。?
???
??sprintf(format,expression1,...)?
???
??跟C語言的sprintf差不多。?
???
??????例如:?
???
??????????sprintf("pi?=?%.2f?(approx.)',22/7)?
???
??????傳回的字串為"pi?=?3.14?(approx.)"?
?
???
??sub(regexp,?replacement,target)?
???
??????在字串?target?里面,尋找符合?regexp?的最長、最靠左邊的地方,并且以字串?
?replacement?代替最左邊的?regexp。?
???
??????例如:?
???
??????????str?=?"water,?water,?everywhere"?
???
??????????sub(/at/,?"ith",str)?
???
??????結果字串str會變成?
???
??????"wither,?water,?everywhere"?
?
???
??gsub(regexp,?replacement,?target)?
???
??????gsub?與前面的?sub?類似。在字串?target?里面,尋找符合?regexp?的所有地方?
,以字串?replacement?代替所有的?regexp。?
???
??????例如:?
???
??????????str="water,?water,?everywhere"?
???
??????????gsub(/at/,?"ith",str)?
???
??????結果字串str會變成?
???
??????'wither,?wither,?everywhere"?
???
??substr(string,?start,?length)?
???
??????傳回字串?string?的子字串,這個子字串的長度為?length?個字符,從第?start?
?個位置開始。?
???
??????例如:?
???
????????substr("washington",5,3)?
???
??????傳回值為"ing"?
???
??????如果?length?沒有出現,則傳回的子字串是從第?start?個位置開始至結束。?
???
??????例如:?
???
??????????substr("washington",5)?
???
??????傳回值為"ington"?
???
??tolower(string)?
???
??????將字串string的大寫字母改為小寫字母。?
???
??????例如:?
???
??????????tolower("MiXeD?cAsE?123")?
???
??????傳回值為"mixed?case?123"?
?
???
??toupper(string)?
???
??????將字串string的小寫字母改為大寫字母。?
???
??????例如:?
???
??????????toupper("MiXeD?cAsE?123")?
???
??????傳回值為"MIXED?CASE?123"?
???
??其他函數?
???
??system(command)?
???
??????此函式允許使用者執行作業系統的指令,執行完畢後將回到?gawk?
???
??????程式。?
???
??????例如:?
???
??????????BEGIN?{system("ls")}?
???
??控制流?
???
??在gawk命令腳本中可以使用控制流,主要是if,for,while等語句,用法和C語言相當?
類似:?
?
???
????if?(condition)?then-body?[else?else-body]?
???
??如果?condition?為真(true),則執行?then-body,否則執行?else-body。?
???
??????舉一個例子如下:?
???
?????????if?(x?%?2?==?0)?
???
?????????????print?"x?is?even"?
???
??????????else?
???
?????????????print?"x?is?odd"?
?
???
??????while?(condition)?
???
?????????????body?
???
??while?語句測試?condition表達式。假如?condition?為真則執行?body?的語句。一次?
執行完後,會再測試?condition,假如condition?為真,則?body?會再度被執行。這個?
過程會一直被重復直到condition?不再是真。如果?condition?第一次測試就是偽(fals?
e),則body?從沒有被執行。?
???
??????下面的例子會印出每個輸入行的前三個欄位。?
???
??????????gawk?'{?i=1?
???
??????????????????while?(i?<=?3)?{?
???
??????????????????????print?$i?
???
??????????????????????i++?
???
??????????????????}?
???
????????????????}'?
???
?????do?
???
????????body?
???
?????while?(condition)?
???
??這個?do?loop?執行?body?一次,然後只要?condition?是真則會重復執行?body。即使?
開始時?condition?是偽,body?也會被執行一次。?
???
??????下面的例子會印出每個輸入記錄十次。?
???
??????????gawk?'{?i=?1?
???
??????????????????do?{?
???
?????????????????????print?$0?
???
?????????????????????i++?
???
??????????????????}?while?(i?<=?10)?
???
??????????}'?
???
????for?(initialization;?condition;?increment)?
???
?????????body?
???
??此敘述開始時會執行initialization,然後只要?condition是真,它?
???
??會重復執行body與做increment?。?
???
??????下面的例子會印出每個輸入記錄的前三個欄位。?
???
??????????gawk?'{?for?(i=1;?i<=3;?i++)?
???
?????????????????????print?$i?
???
??????????}'?
???
??????break?會跳出包含它的?for、while、do-while?循環的最內層。?
???
??????下面的例子會找出任何整數的最小除數,它也會判斷是否為質數。?
???
??????????gawk?'#?find?smallest?divisor?of?num?
???
???????????????{?num=$1?
???
?????????????????for?(div=2;?div*div?<=num;?div++)?
???
????????????????????if?(num?%?div?==?0)?
???
???????????????????????break?
???
?????????????????if?(num?%?div?==?0)?
???
????????????????????printf?"Smallest?divisor?of?%d?is?%d/n",?num,?div?
???
?????????????????else?
???
????????????????????printf?"%d?is?prime/n",?num?}'?
???
??????continue?使用于?for、while、do-while?循環內部,它會跳過循環體的剩余部分?
,立刻進行下一次循環的執行。?
???
??????下面的例子會印出?0?至?20?的全部數字,但是?5?并不會被印出。?
???
??????????gawk?'BEGIN?{?
???
???????????????for?(x=0;?x<=20;?x++)?{?
???
??????????????????if?(x==5)?
???
?????????????????????continue?
???
??????????????????printf?("%d",x)?
???
???????????????}?
???
???????????????print?""?
???
??????????}'?
???
??????next?語句強迫?gawk?立刻停止處理目前的行而繼續下一個輸入行。?
???
??????exit?語句會使得?gawk?程式停止執行而跳出。然而,如果?END?出現,它會去執?
行?END?的?actions。?
?
???
??自定義函數?
???
??你可以定義自己的函數,其格式是?
???
?????function?name?(parameter-list)?{?
???
?????????body-of-function?
???
????????}?
?
???
??name?是所定義的函數名字。?parameter-list?是函數的變量列表。變量間使用逗號分?
開。?
???
??函數可以在程序的任何地方定義,不過習慣上總是定義在程序的開頭部分。?
???
?????下面這個例子,會將每個記錄的第一個欄位之值的平方與第二個欄位之值的平方加?
起來。?
???
??{print?"sum?=",SquareSum($1,$2)}?
?
???
??function?SquareSum(x,y)?{?
???
??????sum=x*x+y*y?
???
??????return?sum?
???
}?
???
??如果你熟悉任何編程語言,那么掌握awk都是很輕松的事情,如果你不喜歡它,那么你?
可以參考我們下面介紹的perl。?
???
??讓我們首先從grep命令開始。這個命令大家應該很熟悉了,它用來在文件中查找一個?
字符串。不過,實際上,grep的處理功能要強大和復雜的多。?
???
??grep?命令的語法是?
???
???grep?[模式]?[文件名]?
???
??如果沒有給出文件名,就缺省使用標準輸入。grep每次讀取一行,并且和給出的模式?
進行匹配,如果成功就把這一行會顯,例如:(粗體的是我們輸入的內容)?
???
??$?grep?test?
???
??close?
???
??test?my?hand?
???
??test?my?hand?
?
???
??grep的“模式”也稱為正則表達式,可以由各種基本的正則表達式元素構成。正則表?
達式元素主要包括下面幾種:?
???
??字符串??????匹配任何字符串,例如grep?test表示在標準輸入中1?
???
???[...]??????????封閉集中匹配一個字符,如:[abcde]可以匹配a,b,c,d,e?
???
??[^...]?????????求補集中匹配一個字符,例如[^ABC]匹配?
???
??.??????????????匹配任意字符?
???
??/s?????????????空白符?
???
??/S?????????????非空白符?
???
??/d?????????????數字?
???
??/D?????????????非數字?
???
??/w?????????????字母或數字?
???
??/W?????????????非字母和數字?
???
??*????????匹配任何字符?
???
??上面的形式是grep中使用的基本正則表達式,另外,還可以使用egrep,egrep是grep?
的一個擴展版本,支持下面這些擴展的正則字符串:?
???
??^??????????????匹配一行的開始?
???
??$??????????????匹配一行的結尾?
???
??(?)????????????確定正則表達式求值順序,和正常演算中的括號意思差不多。?
???
??(...|...|...)??或,可選項之一進行匹配,例如:(abc|dev|ghi)可以匹配abc,dev,gh?
i,而(ww|gg)do可以匹配wwdo或者ggdo。?
???
??+??????????????一次或多次模式?
???
?????????????????如:aba+匹配aba,abaa...不匹配ab?
???
??通常,我們有兩種方法使用grep和egrep,一種是使用管道,例如我們應該熟悉的ps??
ax?|grep?sendmail,另一種是直接在文件中搜索對應的字符串。?
???
??grep/egrep還可以在命令行使用開關,常用的開關包括:?
???
??-b?在行前加上塊號?
???
??-c?統計匹配行的個數?
???
??-n?在行前加上行號?
???
??-w?將模式解釋為字符串,所有正則表達式的控制命令失效?
???
??-x?精確匹配?
???
??-r?查詢文件時包含子目錄?
???
??舉個例子來說,我們想在/var/log/httpd/access_log中查詢所有不是來自本地(192?
.168.0.1)的請求記錄,可以執行:?
???
??grep?–v?"^192.168.0.1"?/var/log/httpd/access_log?
???
??^用來讓grep?只在行首匹配。?
???
??在grep查詢的時候可以使用通配符代表多個文件,例如,grep?start?*?-r將在當前目?
錄以及所有子目錄的所有文件中查詢start字符串。?
???
??11.2.2?gawk的使用方法?
???
??gawk是awk的一個實現,awk是一種用來處理報告等文本文件的腳本語言。不過,我們?
介紹這個產品的主要目標是用它來處理各種程序的記賬文件。對于復雜的腳本,還是用?
Perl比較合適。?
???
??gawk?的主要功能是針對檔案的每一行搜尋指定的?模式。,每當找到一個匹配的模式?
,gawk就會去執行你設定的動作。按照這個方式,?gawk?依此方式處理輸入檔案的每一?
行直到輸入檔案結束。如果對于某個模式沒有設置對應的動作,gawk將直接將這個行顯?
示出來。?
???
??為了使用gawk,你通常必須先寫一個awk腳本,除非模式/動作非常簡單,可以在一行?
上完成。我們用一個例子來解釋gawk的基本用法,首先產生一個目錄列表文件:?
???
??ls?–l?/etc?>?list?
???
??現在list的內容有點像這樣:?
???
??total?2164?
???
??drwxr-xr-x???3?root?????root?????????4096?Feb?15?22:55?CORBA?
???
??-rw-r--r--???1?root?????root?????????2045?Sep?24??1999?DIR_COLORS?
???
??-rw-r--r--???1?root?????root???????????17?Mar?25?19:59?HOSTNAME?
???
??…………?
???
??現在我們選擇一個最簡單的例子,簡單地查找所有屬性是drwxr-xr-x的目錄文件:?
???
??gawk?'/drwxr-xr-x/?{print?$0}'?list?
???
??將輸出所有這樣的目錄。?
???
??這個例子看上去沒有什么實際用處,因為用grep也可以做同樣的動作,那么我們可以?
看一看下面這個功能:?
???
??$?gawk?'$1=="-rwxr-xr-x"??{sum=sum+$5}?END?{print?sum}'?list?
???
??15041?
???
??這個是什么意思?對于所有屬性是755的文件,讓gawk對第五欄的數字求和。第五欄我?
們可以看到就是文件的長度,因此這個命令將顯示所有屬性為755的文件的總共的長度。?
???
??$n是gawk中非常重要的概念,它用來表示文本串的分欄。缺省的情況下,gawk將輸入?
字符串(從文件中讀入的每一行)按照分割的空格分成若干個字段,每個字段作為一個?
變量,例如有一行?
???
??my?name?is?3th?test??
???
??那么,在awk讀入這一行之后,就產生了$1到$5變量,其中$1="my",$2="is",………?
,最后$5="test"。另外還有一個特殊的變量$0,它表示整個輸入行,也就是這個字符串?
"my?name?is?test"。另外還有一個特殊的變量NF,它表示當前行的字段的個數,在現在?
的情況下,NF應該等于5。?
???
??在某些特殊的情況下,你可能需要改變分割符的定義,這可以通過對FS賦值來完成,?
例如FS=","將分割符定義為都號而不是缺省的空格。?
???
??在一般情況下,gawk可以從命令文件中獲得模式/動作,命令文件的格式很簡單,就是?
直接將應該寫在命令行上的模式/動作對寫在文件里面,每個對構成一行,模式可以有兩?
種,一種是模式匹配,也就是我們在前面解釋的正則表達式,如果使用正則表達式,那?
么需要用兩個/把它們夾在一起,例如/[A-Z]/表示正則表達式[A-Z]。?
???
??另一種模式是比較指令,比較指令可以用比較操作符和邏輯運算符來構成,常用的比?
較操作符有:?
???
??==??等于??<=?不大于??~?按照正則表達式匹配?
???
??<??小于??>=?不小于??!~?按照正則表達式不匹配?
???
??>??大于??!=?不等于?
???
??邏輯運算符有?
???
??&&??和??||??或??!?非??()括號?
?
???
??設定了模式后,就可以設置對應的動作了,在gawk中,動作必須用花括號括起來。ga?
wk能完成的動作并不多,畢竟它是一種報告分析語言。一般情況下,只要熟悉print和p?
rintf命令就足夠了,print命令的格式非常簡單:?
???
??print?item1,item2,…………?
???
??輸出時,每個項目輸出一欄,中間用空格分開。一個print后面不跟著任何變量會導致?
gawk顯示當前的輸入行($0)。如果要輸出一個字符串,使用引號把它括起來,特別是?
如果要輸出一個空行,使用print?""。這里是一個例子,它將list文件的頭兩欄輸出:?
???
??????????gawk?'{print?$1,$2}'?list?
???
??由于輸入的文本文件內容有多行,你在命令欄中設計的模式/動作會對每一行執行一次?
。就是:?
???
??total?2164?
???
??drwxr-xr-x?3?
???
??-rw-r--r--?1?
???
??-rw-r--r--?1?
???
??-rw-r--r-1?
???
??…………………?
???
??如果你要精確地控制輸出,也可以使用printf命令,這個命令的格式是:?
???
?????printf?format,?item1,?item2,?...?
???
?????format參數就是C語言里面的格式控制符,例如%c,%d,%f等等。在?%?與格式控制?
字母之間可加入?modifier,modifier?是用來進一步控制輸出的格式。可能的?modifie?
r?如下所示:?
???
??'-'?????使用在?width?之前,指明是向左靠齊。如果'-'沒有出現,則會在被指定的?
寬度向右靠齊。例如:?
???
??????????printf?"%-4S",?"foo"會印出'foo?'。?
???
??'width'?這一個數字指示相對應的欄位印出時的寬度。例如:?
???
???printf?"%4s","foo"?????會印出'?foo'。?
???
??????????width?的值是一個最小寬度而非最大寬度。如果一個?item?的值需要的寬度?
比?width?大,則不受?width?的影響。例如printf?"%4s","foobar"將印出'foobar'。?
???
??'.prec'?此數字指定印出時的精確度。它指定小數點右邊的位數。如果是要印出一個?
字串,它指定此字串最多會被印出多少個字符。?
???
??作為一種腳本語言,gawk允許使用變量,定義變量非常簡單,就是直接用等號對它賦?
值。為了在gawk程序的開始處對變量賦值,gawk專門提供了BEGIN語句,這個語句將在所?
有行被讀入之前執行,而且只執行一次,通常用它來執行初始化命令,例如?
???
??BEGIN?{?sum=0;count=0;average=0.0;}?
???
??對于變量可以使用數學表達式進行運算,運算符包括常見的加減乘除算符,以及^(乘?
方),%(取余)和著名的++,--。不過注意gawk在做除法的時候總是使用浮點除法,除了?
取余算符%。?
???
??函數?
???
??另外,gawk包含下列函數:?
???
??數學函數?
???
??atan2(x,y)??????y/x的正切?
???
??cos(x)????余弦函數?
???
??sin(x)????正弦函數?
???
??int(x)????取整?
???
??log(x)????取自然對數?
???
??exp(x)????指數函數?
???
??rand(x)????生成一個0到1之間的隨機數?
???
??srand()????初始化隨機數發生器?
???
??systime()????返回從1970年1月1日0:00到當前時間的秒數?
???
??sqrt(x)????取x的平方根?
???
??字符串函數?
???
??index(string1,string2?)?
???
??????它會在string1?里面,尋找string2?第一次出現的地方,返回值是字串string2出?
現在字串string1?里面的位置。如果找不到,返回值為?0。?
???
??????例如:?
???
??????????print?index("peanut","an")?
???
??????會印出?3。?
???
??length(string)?
???
??string字符串的長度?
???
??????例如:?
???
??????????length("abcde")?
???
??????是?5。?
???
??match(string,regexp)?
???
??????match?函數會在字串?string?里面,尋找符合?regexp?的最長、最靠左邊的子字?
串。返回值是?regexp?在?string?的開始位置,即?index值。這個函數會設定內部變量?
?RSTART?等於?index,內部變量RLENGTH?等於符合的子串個數。如果不符合,則會設定?
?RSTART?為0、RLENGTH?為?-1。?
???
??sprintf(format,expression1,...)?
???
??跟C語言的sprintf差不多。?
???
??????例如:?
???
??????????sprintf("pi?=?%.2f?(approx.)',22/7)?
???
??????傳回的字串為"pi?=?3.14?(approx.)"?
?
???
??sub(regexp,?replacement,target)?
???
??????在字串?target?里面,尋找符合?regexp?的最長、最靠左邊的地方,并且以字串?
?replacement?代替最左邊的?regexp。?
???
??????例如:?
???
??????????str?=?"water,?water,?everywhere"?
???
??????????sub(/at/,?"ith",str)?
???
??????結果字串str會變成?
???
??????"wither,?water,?everywhere"?
?
???
??gsub(regexp,?replacement,?target)?
???
??????gsub?與前面的?sub?類似。在字串?target?里面,尋找符合?regexp?的所有地方?
,以字串?replacement?代替所有的?regexp。?
???
??????例如:?
???
??????????str="water,?water,?everywhere"?
???
??????????gsub(/at/,?"ith",str)?
???
??????結果字串str會變成?
???
??????'wither,?wither,?everywhere"?
???
??substr(string,?start,?length)?
???
??????傳回字串?string?的子字串,這個子字串的長度為?length?個字符,從第?start?
?個位置開始。?
???
??????例如:?
???
????????substr("washington",5,3)?
???
??????傳回值為"ing"?
???
??????如果?length?沒有出現,則傳回的子字串是從第?start?個位置開始至結束。?
???
??????例如:?
???
??????????substr("washington",5)?
???
??????傳回值為"ington"?
???
??tolower(string)?
???
??????將字串string的大寫字母改為小寫字母。?
???
??????例如:?
???
??????????tolower("MiXeD?cAsE?123")?
???
??????傳回值為"mixed?case?123"?
?
???
??toupper(string)?
???
??????將字串string的小寫字母改為大寫字母。?
???
??????例如:?
???
??????????toupper("MiXeD?cAsE?123")?
???
??????傳回值為"MIXED?CASE?123"?
???
??其他函數?
???
??system(command)?
???
??????此函式允許使用者執行作業系統的指令,執行完畢後將回到?gawk?
???
??????程式。?
???
??????例如:?
???
??????????BEGIN?{system("ls")}?
???
??控制流?
???
??在gawk命令腳本中可以使用控制流,主要是if,for,while等語句,用法和C語言相當?
類似:?
?
???
????if?(condition)?then-body?[else?else-body]?
???
??如果?condition?為真(true),則執行?then-body,否則執行?else-body。?
???
??????舉一個例子如下:?
???
?????????if?(x?%?2?==?0)?
???
?????????????print?"x?is?even"?
???
??????????else?
???
?????????????print?"x?is?odd"?
?
???
??????while?(condition)?
???
?????????????body?
???
??while?語句測試?condition表達式。假如?condition?為真則執行?body?的語句。一次?
執行完後,會再測試?condition,假如condition?為真,則?body?會再度被執行。這個?
過程會一直被重復直到condition?不再是真。如果?condition?第一次測試就是偽(fals?
e),則body?從沒有被執行。?
???
??????下面的例子會印出每個輸入行的前三個欄位。?
???
??????????gawk?'{?i=1?
???
??????????????????while?(i?<=?3)?{?
???
??????????????????????print?$i?
???
??????????????????????i++?
???
??????????????????}?
???
????????????????}'?
???
?????do?
???
????????body?
???
?????while?(condition)?
???
??這個?do?loop?執行?body?一次,然後只要?condition?是真則會重復執行?body。即使?
開始時?condition?是偽,body?也會被執行一次。?
???
??????下面的例子會印出每個輸入記錄十次。?
???
??????????gawk?'{?i=?1?
???
??????????????????do?{?
???
?????????????????????print?$0?
???
?????????????????????i++?
???
??????????????????}?while?(i?<=?10)?
???
??????????}'?
???
????for?(initialization;?condition;?increment)?
???
?????????body?
???
??此敘述開始時會執行initialization,然後只要?condition是真,它?
???
??會重復執行body與做increment?。?
???
??????下面的例子會印出每個輸入記錄的前三個欄位。?
???
??????????gawk?'{?for?(i=1;?i<=3;?i++)?
???
?????????????????????print?$i?
???
??????????}'?
???
??????break?會跳出包含它的?for、while、do-while?循環的最內層。?
???
??????下面的例子會找出任何整數的最小除數,它也會判斷是否為質數。?
???
??????????gawk?'#?find?smallest?divisor?of?num?
???
???????????????{?num=$1?
???
?????????????????for?(div=2;?div*div?<=num;?div++)?
???
????????????????????if?(num?%?div?==?0)?
???
???????????????????????break?
???
?????????????????if?(num?%?div?==?0)?
???
????????????????????printf?"Smallest?divisor?of?%d?is?%d/n",?num,?div?
???
?????????????????else?
???
????????????????????printf?"%d?is?prime/n",?num?}'?
???
??????continue?使用于?for、while、do-while?循環內部,它會跳過循環體的剩余部分?
,立刻進行下一次循環的執行。?
???
??????下面的例子會印出?0?至?20?的全部數字,但是?5?并不會被印出。?
???
??????????gawk?'BEGIN?{?
???
???????????????for?(x=0;?x<=20;?x++)?{?
???
??????????????????if?(x==5)?
???
?????????????????????continue?
???
??????????????????printf?("%d",x)?
???
???????????????}?
???
???????????????print?""?
???
??????????}'?
???
??????next?語句強迫?gawk?立刻停止處理目前的行而繼續下一個輸入行。?
???
??????exit?語句會使得?gawk?程式停止執行而跳出。然而,如果?END?出現,它會去執?
行?END?的?actions。?
?
???
??自定義函數?
???
??你可以定義自己的函數,其格式是?
???
?????function?name?(parameter-list)?{?
???
?????????body-of-function?
???
????????}?
?
???
??name?是所定義的函數名字。?parameter-list?是函數的變量列表。變量間使用逗號分?
開。?
???
??函數可以在程序的任何地方定義,不過習慣上總是定義在程序的開頭部分。?
???
?????下面這個例子,會將每個記錄的第一個欄位之值的平方與第二個欄位之值的平方加?
起來。?
???
??{print?"sum?=",SquareSum($1,$2)}?
?
???
??function?SquareSum(x,y)?{?
???
??????sum=x*x+y*y?
???
??????return?sum?
???
}?
???
??如果你熟悉任何編程語言,那么掌握awk都是很輕松的事情,如果你不喜歡它,那么你?
可以參考我們下面介紹的perl。?
總結
- 上一篇: linux grep sed awk
- 下一篇: 基本SQL