簡介
1.概述
awk、sed和grep,俗稱linux下的三劍客,它們之間有很多相似點,但是同樣也各有個的特色,相似的地方是它們可以比對文本,其中sed和awk還可以用于文本編輯,而grip則不具備這個功用。sed是一種非互動式且面向字元劉德編輯器(a “non-interactive” stream-oriented editor),而awk則是一門模式比對的程式設計語言,因為它主要功能是用于比對文本并處理,同時它有一些變成語言才有的文法,例如函數、分支循環語句、變量等等,當然比起我們常見的程式設計語言,awk相對比較簡單。
awk是一個強大的文本分析工具,相對與grep的查找,sed的編輯,awk在其對資料分析并生成報告時,顯得尤為強大。簡單來說awk就是把檔案逐行的讀入,以空格為預設分割符将每行切片,切開的部分再進行各種分析處理。
awk有3個不同版本: awk、nawk和gawk,未作特别說明,一般指gawk,gawk 是 awk 的 gnu 版本。
awk其名稱得自于它的創始人 alfred aho 、peter weinberger 和 brian kernighan
姓氏的首個字母。實際上 awk 的确擁有自己的語言: awk 程式設計語言 ,
三位建立者已将它正式定義為“樣式掃描和處理語言”。它允許您建立簡短的程式,這些程式讀取輸入檔案、為資料排序、處理資料、對輸入執行計算以及生成報
表,還有無數其他的功能。
2.原理
1)awk的輸入被解析成多個記錄(record),預設情況下,記錄的分割符是\n,是以可以認為一行就是一個記錄,記錄的分割符可以通過内置變量rs更改。檔記錄比對某個pattern時,才會執行後續的action指令。
每個記錄又進一步被分割成多個字段(field),預設情況下字元的分割符是空白符,例如空格、制表符等,也可以通過-f ere 選項或内置變量fs更改。在awk中,可以通過$1,$2,...來通路對應位置的字段,同時¥0存放整個記錄。
2)awk基本結構包括模式比對(用于找到要處理的行)和處理過程(即處理動作)
pattern {action}
說明:awk讀取檔案内容的每一行時,将對比該行是否與給定的模式相比對,如果比對則執行處理過程,否則對該行不做任何處理。
如果沒有制定處理腳本,則把比對的行顯示到标準輸出,即預設處理動作是print列印行;
如果沒有制定模式比對,則預設比對所有資料。
3)awk有兩個特殊的模式:begin和end,它們被防止在沒有讀取任何資料之前以及在所有資料讀取完成以後執行。
3.使用awk,可以做:
将文本檔案視為由字段和記錄組成的文本資料庫
在操作文本資料庫的過程中能夠使用變量
能夠使用數學運算和字元串操作
能夠使用常見的變成結構,例如條件分支與循環
能夠格式化輸出
能夠自定義函數
能夠在awk腳本中執行unix指令
能夠處理unix指令的輸出結果
其他
使用方法
有三種方式調用awk
指令行方式(其實就上上面的1/3):
标準的awk指令行參數主要有以下三個:
-f ere:定義字段分割符,該選項的值可以是擴充的正規表達式(ere);
-f progfile:指定awk腳本,可以同時制定多個腳本,它們會按照在指令行中出現的順序連接配接在一起;
-c assignment:定義awk變量,形式同awk中的變量指派,即name=value,複制發生在awk處理文本之前。
簡單示例:
1)指定分割符為冒号,并列印各個字段
2)通過正規表達式“/^$”比對空白行,動作為列印空行,檔案中有幾個空白行,就列印幾個空白行
3)列印包含主機名的行,因為沒有制定動作指令,預設動作為列印
4)在awk腳本中通路通過-v選項設定的變量
5)提前編輯一個awk腳本,再通過-f選項調用該腳本
awk基本操作
1. 記錄與字段
awk一次從檔案中讀取一條記錄,并将記錄存儲在字段變量$0中。記錄被分割為字段并存儲在$1,$2 ..., $nf中(預設使用空格或制表符為分隔符)。
内建變量nf為記錄的字段個數
示例:
[jacob@localhost ~]# echo hello the world |
>awk '{print $1,$2,$3}'
備注:讀取輸入行并輸出第一個字段,第二個字段,第三個字段。
>
備注:讀取輸入行并輸出該行。
>awk '{print nf}'
備注:讀取輸入行并輸出該行的字段個數:3個字段。
>awk '{print $nf}'
備注:讀取輸入行并輸出該行的第三個字段,因為nf為3,是以$nf等同于取行的最後一個字段。
2. 字段分隔符
預設awk讀取資料以空格或制表符作為分隔符,但可以通過-f或fs(field separator)變量來改變分隔符。
[jacob@localhost ~]# awk -f: '{print $1}' /etc/passwd
[jacob@localhost ~]# awk 'begin {fs = ":"} {print $1}' /etc/passwd
備注:以上兩個示例均将字段的分隔符改冒号(:),即以冒号為分隔符列印passwd檔案的第一個字段(帳号名稱)。
注意:如果使用fs改變分隔符的話,需要在begin處定義fs,因為在讀取第一行前就需要改變字段分隔符。
進階:指定多個字段分隔符(文檔内容為:hello the:word,!)
[jacob@localhost ~]# echo 'hello the:word,!' |
>awk 'begin {fs="[:, ]"} {print $1,$2,$3,$4}'
3. 内置變量
以下為awk内置變量:
argc 指令行參數個數
filename 目前輸入文檔的名稱
fnr 目前輸入文檔的目前記錄編号,尤其當有多個輸入文檔時有用
nr 輸入流的目前記錄編号
nf 目前記錄的字段個數
fs 字段分隔符
ofs 輸出字段分隔符,預設為空格
ors 輸出記錄分隔符,預設為換行符\n
rs 輸入記錄分隔符,預設為換行符\n
[jacob@localhost ~]# cat test1.txt
[jacob@localhost ~]#cat test2.txt
[jacob@localhost ~]# awk '{print fnr}' test1.txt test2.txt
備注:輸出目前文檔的目前行編号,第一個檔案兩行,第二個檔案三行。
[jacob@localhost ~]# awk '{print nr}' test1.txt test2.txt
備注:awk将兩個文檔作為一個整體的輸入流,通過nr輸入目前行編号。
[jacob@localhost ~]# awk '{print nf}' test1.txt
備注:test1.txt文檔的第一行有5個字段,第二行有4個字段。
[jacob@localhost ~]# awk '{print $1,$2,$3}' test1.txt
備注:預設print輸出時,各參數将的輸出分隔符預設為空格,是以輸出内容如下
this is a
welcome to jacob's
[jacob@localhost ~]# awk 'begin {ofs="-"} {print $1,$2,$3}' test1.txt
備注:通過ofs将輸出分隔符設定為"-",這個print在輸出第一、二、三個字段時,中間的分隔符為"-",結果如下
[jacob@localhost ~]# cat test3.txt
[jacob@localhost ~]# awk 'begin {fs="\n"; rs=""} {print $3}' test3.txt
備注:讀取輸入資料,以空白行為記錄分隔符,即第一個空白行前的内容為第一個記錄,第一個記錄中字段分隔符為換行符。
以上awk的效果為列印所有的郵件時間,即每個記錄的第三個字段。
4. 表達式與操作符
表達式是由變量、常量、函數、正規表達式、操作符組成,awk中變量有字元變量和數字變量。如果在awk中定義的變量沒有初始化,則初始值為空字串或0。
注意:字元操作時一定記得需要加引号
1) 變量定義示例:
a="welcome to beijing"
b=12
2) 操作符(awk操作符與c語言類似)
+ 加
- 減
* 乘
/ 除
% 取餘
^ 幂運算
++ 自加1
-- 自減1
+= 相加後指派給變量(x+=9等同于x=x+9)
-= 相減後指派給變量(x-=9等同于x=x-9)
*= 相乘後指派給變量(x*=9等同于x=x*9)
/= 相除後指派給變量(x/=9等同于x=x/9)
> 大于
< 小于
>= 大于等于
<= 小于等于
== 等于
!= 不等于
~ 比對
!~ 不比對
&& 與
|| 或
操作符簡單示例:
[jacob@localhost ~]# echo "test" | awk 'x=2 {print x+3}'
[jacob@localhost ~]# echo "test" | awk 'x=2,y=3 {print x*2, y*3}'
[jacob@localhost ~]# awk '/^$/ {print x+=1}' test.txt 備注:統計所有空白行
[jacob@localhost ~]# awk '/^$/ {x+=1} end {print x}' test.txt 備注:列印總空白行個數
[jacob@localhost ~]# awk -f: '$1~/root/ {print $3}' /etc/passwd 備注:列印root的id号
[jacob@localhost ~]# awk -f: '$3>500 {print $1}' /etc/passwd 備注:列出計算機中id号大于500的使用者名
awk條件及循環語句
1. if條件判斷格式:
if (表達式)
動作1
else
動作2
或者if (表達式) 動作1;else 動作2
說明:如果表達式的判斷結果為真則執行動作1,否則執行動作2。
示例:(判斷boot分區可用容量小于20m時報警,否則顯示ok)
[jacob@localhost ~]# df |grep "boot" |awk '{if($4<20000) print "alart"; else print "ok"}'
2. 循環
while (條件)
動作
x=1
while (i < 10) {
print $i
}
[jacob@localhost ~]# awk 'i=1 {} begin { while (i<=10) {++i; print i}}' test.txt
do
[jacob@localhost ~]# awk 'begin { do {++x;print x} while (x<=10)}' test.txt
for (變量;條件;計數器)
for (i=1;i<=10;i++)
print i
[jacob@localhost ~]# awk 'begin {for(i=1;i<=10;i++) print i}' test.txt
[jacob@localhost ~]# awk 'begin {for(i=10;i>=1;i--) print i}' test.txt
說明:因為以上循環語句使用的awk均使用的begin模式,是以輸入文檔可以為任意文檔(無關緊要)。
3. break與continue
break 跳出循環
continue 終止目前循環
for (i=1; i<=10;i++) {
if (i=5)
continue
說明:列印1-4,6-10
break
說明:僅列印1-4
主要參考博文:“丁丁曆險” http://manual.blog.51cto.com/3300438/932958