awk(一)基礎篇

上一篇總結了下sed的用法,這一篇玩玩sed的好×××awk,學完它倆,以後就再也不用怕處理文本文件了。

awk其實和sed處理過程差不多,都是面向字符流的。sed和awk都相當於是一個加工廠,輸入的文本行,相當於原材料,原材料在工廠中經過一系列處理。然後輸出成品。

awk和sed不同的是,awk更加的強大了,基本上可以說大多數sed能夠實現的功能,awk都可以實現。。。。

但是實現相同的功能,大多情況下sed的過程更加的簡潔吧。

當然awk還有着更多的功能,awk本身就是一門類C的語言了,有變量,有流程控制,有函數。可以針對單行,多行,字段等進行更多的處理。

OK,先說說awk的架構吧

架構

awk腳本,可以說由三個例程組成。

例程長什麼樣的呢?

長這樣的:模式{}

模式用於匹配,{}裏面的東西,是對匹配成功的東西,處理的過程

OK,看看是哪三個吧?

awk  'BEGIN{} /正則/{} END{}' file

當然這三類例程,每類例程都是可選的,可以不出現,出現一次,或多次都可以。

wKiom1PDPaCi-qlqAAGqkgSldys881.jpg 詳細說說三類例程。

BEGIN{}:BEGIN規則相關的例程,處理輸入前將做的處理。 這個例程是不讀取文件輸入行的,從上面 的圖中可以看到

/正則/{}:主輸入循環例程,處理輸入過程中將做的處理。這個例程其實就是awk爲我們封裝好的一個循環框架,循環變量是滿足匹配模式的行,循環終止條件是所有匹配的行都處理完了。所以循環的次數和匹配的行數相同,無輸入或無匹配的行,循環將不執行。。如果沒有/正則/這種模式匹配,則所有輸入行都執行循環

END{}:END規則相關的例程,處理輸入後將做的處理。這個例程主要做些掃尾的工作,比如主輸入循環中的最後的結果,在END{}中輸出

畫個圖,看一下三個例程的執行過程。

wKioL1PDQ9jDGLSBAAD9WNmN4RU519.jpg

OK,我們再看看三個例程的變量,是怎麼用的

wKiom1PDQufh9RaKAAEl69ECbyg901.jpg

看到了吧,這三個小例子說明了,

1.前面例程定義的變量,在該例程執行完畢後,變量並不會消失,而是可以被後續的例程繼續使用。

2.後面例程定義的變量,前面的例程卻不可以使用的。這個想想也就明白了,你前面的例程都執行完畢了,我後面的變量還沒定義呢,你怎麼能使用我的變量呢?

模式匹配

可以是以下幾種方式

/regular expression/

relational expression

BEGIN

END

pattern,pattern

1.正則表達式使用元字符的擴展集,並且必須用//斜槓包圍,

2.關係表達式使用關係操作符

root@salt-master:~/sedAawk/awk# awk 'NF>2?/^an/:/^pu/'  test
ansible  a one of its most powerful tools
puppet?

3.BEGIN模式在第一個輸入行被讀取前使用,END模式在最後一個輸入行被讀取之後應用

4.使用!可以否定匹配,也就是處理和模式不匹配的行

root@salt-master:~/sedAawk/awk# awk '!NF>2?/^an/:/^pu/{print}'  test
puppet?

5.可以訪問若干行,和sed中一樣。pattern1,pattern2

root@salt-master:~/sedAawk/awk# awk '/^an/,/pu/'  test
ansible  a one of its most powerful tools
salt-stack also 
puppet?
root@salt-master:~/sedAawk/awk# awk 'NR==1,NR==2'  test
ansible  a one of its most powerful tools
salt-stack also

6.除了BEGIN和END模式,都可以使用&&,||

root@salt-master:~/sedAawk/awk# awk '/^an/||/pu/'  test
ansible  a one of its most powerful tools
puppet?

7.可以將模式放在圓括號裏,確保正確的求值

root@salt-master:~/sedAawk/awk# awk '(/^an/||/pu/)'  test
ansible  a one of its most powerful tools
puppet?
root@salt-master:~/sedAawk/awk# awk '!(/^an/||/pu/)'  test
salt-stack also 
chef? I do not know
root@salt-master:~/sedAawk/awk# awk '!/^an/||/pu/'  test
salt-stack also 
puppet?
chef? I do not know

8.BEGIN和END必須和操作相聯繫,如果編寫了多個BEGIN或END規則,它們在應用前被合成一個規則




記錄和字段

說到底awk主要還是要用來處理文本文件,我們最應該關注的還是主輸入循環例程,而BEGIN和END,則可以讓我們的處理過程更加的靈活強大

OK,來看看什麼是記錄和字段吧

記錄:就是我們輸入文本的每一行,就叫做一條記錄。在awk中可以用$0這個變量表示

字段:就是我們每條記錄按照特定的分隔符去分割,分割後每個小片段就是一個字段,用$1,$2,...表示

OK,說到字段,字段的劃分是繞不過的一個話題。

看一下,怎麼選定分隔符去劃分字段吧,一共有兩種方法去劃分字段。

第一種方法使用-F參數,舉個小例子

wKiom1PDS36BdlIcAAGFJfqpdMU817.jpg

分割符可以用圖中的幾種方式去表示

  1. 默認情況下爲空格或製表符

  2. 可以指定分割符爲某一字符,加在-F參數的後面,可以緊挨着-F,用''或""括起來

  3. 可以用正則表達式來,表示分隔符

  4. 可以指定多個分割符

第二種方法,使用awk提供的一個系統變量FS,翻譯成英文是field segmentation,意思就是字段分割

OK,看一下怎麼用

wKioL1PDTT7QZPbtAAEDE0IwKd4206.jpg

使用FS這個系統變量指定分割符的時候,分隔符的形式和-F參數的那四種形式是一樣的。。。

不過我們一般把FS變量,定義在BEGIN例程中,當然也可以在命令行的-v參數後面。

注意:我們上面講的字段分割,如果在記錄的最開頭和最結尾出現分割符,會被awk忽略的


說完了記錄和字段,輸入這一塊就差不多了,記錄輸入之後,就是處理的過程了。這也是主輸入循環例程,主要乾的活

主輸入循環的處理過程,主要由語句,函數和表達式組成的了

表達式

表達式可以用來存儲,操作和檢索數據。一個表達式,通過計算一個返回值。

表達式由數字,字符串常量,變量,操作符,函數和正則表達式組成。

這裏先主要說說,常量,變量,操作符。。函數下一篇說

常量

awk中的常量有兩種,一個數字,二是字符串。一般用''或者""括起來,

注意:命令行上使用字符串,要用"",避免shell的影響

字符串中,可以使用轉義字符

\a,\b,\f,\n,\r,\t,\v,\ddd,\xbex,\c

變量

awk的變量和別的語言的變量有些不同。

1.awk的每個變量都有,字符串型值和數字型值。awk能夠根據表達式的前後關係,來自動的選取合適的值。

2.變量不必初始化,awk會自動把它們初始化爲空字符串,如果作爲數字,值則爲0

如awk 'BEGIN{print a}'  ,結果爲空

操作符

算術操作符

+,-,*,/,%,^(取冪)

賦值運算符

++,--,+=,-=,*=,/=,%=,^=

關係操作符和布爾操作符主要用於兩個表達式之間的比較

關係操作符

<,>,<=,>=,==,!=,~(匹配),!~(不匹配)

布爾操作符

||

&&

!

系統變量

變量名用途
FS(Field segmentation)(可改變)域分隔符,默認爲空格或製表符,可自定義爲任意單個或多個字符,及正則表達式
OFS(output Field segmentation)(可改變)
和FS等效的輸出域分隔符,默認爲空格
NF(Number Fields)(不要改變)
當前輸入記錄的字段個數,最好不要人爲的去改變這個值
RS(Record segmentation)(可改變)
記錄分隔符,默認爲一個換行符。在處理多行記錄的時候,我們可能會把RS的值,改變
ORS(output Record segmentation)(可改變)和RS對應的輸出記錄分隔符,它的默認值也是一個換行符
FILENAME(不要改變)
輸入文件的名稱
NR(Number Record)(不要改變)
當前輸入記錄的編號,可以跨越多個文件
FNR(File Numberr Record)(不要改變)當前文件記錄的編號,跨文件的話,會重新從0開始
ARGC(不要改變)命令行參數個數
ARGV(不要改變)命令行參數數組
OFMT控制數字到字符串轉換,這個適合樓主的環境(mawk),現在不適合gawk了。。。。gawk用CONVFMT
ENVIRON
UNIX環境變量
ERRNO
UNIX系統錯誤消息
IGNORECASE如果爲真,則忽略大小寫的匹配
RSTART
被匹配函數,匹配的字符串首
RLENGTH被匹配函數的字符串長度
SUBSEP\034

這麼多系統變量,其實前10個會被經常用到。。。後面那幾個,咱們平時分析個日誌,基本上不會用到這些東西,在這裏mark下,就不細說了。

第一組:FS,OPF,NF  這三個變量,都是針對字段的,看個例子

wKiom1PDvqqxlleaAADnkH9jvwI226.jpg

第二組:RS,ORS,NR,FNR這四個變量,都是針對記錄的,看個例子

wKioL1PDwF-DfbOaAADi-rxMnFY330.jpg

wKioL1PDwOWzbxwSAABnyiMtNHM802.jpg

其它的都用處不大,就不細究了。

格式化打印

和c語言中的printf一樣。

print和printf相比有啥優點呢?

唯一的優點就是,print是自動換行的,而printf要自己加\n,參數才能換行

printf語法格式

printf (for mat-expression [,arguments])

printf格式說明符

c,d,i,e,E,f,g,G,O,s,u,x,X,%

最常用的就仨,%d(數字),%s(字符串),%f(浮點數)

寬度和精度

格式:%寬度.精度 格式說明符

舉個例子大夥就知道怎麼用了

wKioL1PDxUyDBNCWAAFGig8ZJFQ452.jpg

命令行參數

兩種方法:

看個例子

wKiom1PDxzexkALvAADALHhZzDA569.jpg

注意:

當使用awk -v var=argument時候,變量首先就會被傳遞給BEGIN相關的例程

而使用awk '' var=argument的時候,變量在BEGIN例程中是不可用的。

這是爲什麼呢?

因爲後面傳遞過來的參數,就像文件一樣被處理,賦值操作直到主循環例程開始執行時,纔會發生。

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