awk是一種編程語言,用於在linux/unix下對文本和數據進行處理。數據能夠來自標準輸入、一個或多個文件,或其它命令的輸出。它支持用戶自定義函數和動態正則表達式等先進功能,是linux/unix下的一個強大編程工具。它在命令行中使用,但更可能是做爲腳原本使用。mysql
awk的處理文本和數據的方式:它逐行掃描文件,從第一行到最後一行,尋找匹配的特定模式的行,並在這些行上進行你想要的操做。若是沒有指定處理動做,則把匹配的行顯示到標準輸出(屏幕),若是沒有指定模式,則全部被操做所指定的行都被處理。linux
awk分別表明其做者姓氏的第一個字母。由於它的做者是三我的,分別是Alfred Aho、Brian Kernighan、Peter Weinberger。正則表達式
gawk是awk的GNU版本,它提供了Bell實驗室和GNU的一些擴展。下面介紹的awk是以GUN的gawk爲例的,在linux系統中已把awk連接到gawk,因此下面所有以awk進行介紹。sql
2.1 awk的語法有兩種形式express
1. 命令行方式
awk [-F field-separator] 'commands' input-file(s)
其中,commands是真正awk命令,[-F域分隔符]是可選的。input-file(s)是待處理的文件。
在awk中,文件的每一行中,由域分隔符分開的每一項稱爲一個域。一般,在不指名-F域分隔符的狀況下,默認的域分隔符是空格。
2. 將全部的awk命令插入一個單獨文件,而後調用:
awk -f awk-script-file input-file(s)
其中,-f選項加載awk-script-file中的awk腳本,input-file(s)跟上面的是同樣的。編程
2.2 命令選項數組
(1)-F fs or --field-separator fs :指定輸入文件折分隔符,fs是一個字符串或者是一個正則表達式,如-F:。編程語言
(2)-v var=value or --asign var=value :賦值一個用戶定義變量。函數
(3)-f scripfile or --file scriptfile :從腳本文件中讀取awk命令。工具
(4)-mf nnn and -mr nnn :對nnn值設置內在限制,-mf選項限制分配給nnn的最大塊數目;-mr選項限制記錄的最大數目。這兩個功能是Bell實驗室版awk的擴展功能,在標準awk中不適用。
(5)-W compact or --compat, -W traditional or --traditional :在兼容模式下運行awk。因此gawk的行爲和標準的awk徹底同樣,全部的awk擴展都被忽略。
(6)-W copyleft or --copyleft, -W copyright or --copyright :打印簡短的版權信息。
(7)-W help or --help, -W usage or --usage :打印所有awk選項和每一個選項的簡短說明。
(8)-W lint or --lint :打印不能向傳統unix平臺移植的結構的警告。
(9)-W lint-old or --lint-old :打印關於不能向傳統unix平臺移植的結構的警告。
(10)-W posix :打開兼容模式。但有如下限制,不識別:/x、函數關鍵字、func、換碼序列以及當fs是一個空格時,將新行做爲一個域分隔符;操做符**和**=不能代替^和^=;fflush無效。
(11)-W re-interval or --re-inerval :容許間隔正則表達式的使用,參考(grep中的Posix字符類),如括號表達式[[:alpha:]]。
(12)-W source program-text or --source program-text :使用program-text做爲源代碼,可與-f命令混用。
(13)-W version or --version :打印bug報告信息的版本。
#awk '{pattern + action}' {filenames}
儘管操做可能會很複雜,但語法老是這樣,其中 pattern 表示 AWK 在數據中查找的內容,而 action 是在找到匹配內容時所執行的一系列命令。花括號({})不須要在程序中始終出現,但它們用於根據特定的模式對一系列指令進行分組。 pattern就是要表示的正則表達式,用斜槓括起來。
awk語言的最基本功能是在文件或者字符串中基於指定規則瀏覽和抽取信息,awk抽取信息後,才能進行其餘文本操做。完整的awk腳本一般用來格式化文本文件中的信息。
一般,awk是以文件的一行爲處理單位的。awk每接收文件的一行,而後執行相應的命令,來處理文本。
awk腳本是由模式和操做組成的:
pattern {action} 如$ awk '/root/' test,或$ awk '$3 < 100' test。
二者是可選的,若是沒有模式,則action應用到所有記錄,若是沒有action,則輸出匹配所有記錄。默認狀況下,每個輸入行都是一條記錄,但用戶可經過RS變量指定不一樣的分隔符進行分隔。
3.1. 模式
模式能夠是如下任意一個:
(1)正則表達式:使用通配符的擴展集。
(2)關係表達式:能夠用下面運算符表中的關係運算符進行操做,能夠是字符(3)串或數字的比較,如$2>%1選擇第二個字段比第一個字段長的行。
(4)模式匹配表達式:用運算符~(匹配)和~!(不匹配)。
(5)模式,模式:指定一個行的範圍。該語法不能包括BEGIN和END模式。
(6)BEGIN:讓用戶指定在第一條輸入記錄被處理以前所發生的動做,一般可在這裏設置全局變量。
(7)END:讓用戶在最後一條輸入記錄被讀取以後發生的動做。
3.2. 操做
操做由一人或多個命令、函數、表達式組成,之間由換行符或分號隔開,並位於大括號內。主要有四部份:
(1)變量或數組賦值
(2)輸出命令
(3)內置函數
(4)控制流命令
變量 |
描述 |
$n |
當前記錄的第n個字段,字段間由FS分隔。 |
$0 |
完整的輸入記錄。 |
ARGC |
命令行參數的數目。 |
ARGIND |
命令行中當前文件的位置(從0開始算)。 |
ARGV |
包含命令行參數的數組。 |
CONVFMT |
數字轉換格式(默認值爲%.6g) |
ENVIRON |
環境變量關聯數組。 |
ERRNO |
最後一個系統錯誤的描述。 |
FIELDWIDTHS |
字段寬度列表(用空格鍵分隔)。 |
FILENAME |
當前文件名。 |
FNR |
同NR,但相對於當前文件。 |
FS |
字段分隔符(默認是任何空格)。 |
IGNORECASE |
若是爲真,則進行忽略大小寫的匹配。 |
NF |
當前記錄中的字段數。 |
NR |
當前記錄數。 |
OFMT |
數字的輸出格式(默認值是%.6g)。 |
OFS |
輸出字段分隔符(默認值是一個空格)。 |
ORS |
輸出記錄分隔符(默認值是一個換行符)。 |
RLENGTH |
由match函數所匹配的字符串的長度。 |
RS |
記錄分隔符(默認是一個換行符)。 |
RSTART |
由match函數所匹配的字符串的第一個位置。 |
SUBSEP |
數組下標分隔符(默認值是/034)。 |
e.g 有兩個文件a 和b
awk '{if(ARGIND==1){print "處理a文件"} if(ARGIND==2){print "處理b文件"}}' a b
文件處理的順序是先掃描完a文件,再掃描b文件
NR 已經讀出的記錄數
FNR 當前文件的記錄數
上面的例子也能夠寫成這樣:
awk 'NR==FNR{print "處理文件a"} NR > FNR{print "處理文件b"}' a b
輸入文件a和b,因爲先掃描a,因此掃描a的時候必然有NR==FNR,而後掃描b的時候,FNR從1開始計數,而NR則接着a的行數繼續計數,因此NR > FNR
e.g 要顯示文件的第10行至第15行
awk 'NR==10,NR==15{print}' a
FS 輸入字段分隔符(缺省爲:space:),至關於-F選項
awk -F ':' '{print}' a 和 awk 'BEGIN{FS=":"}{print}' a 是同樣的
OFS輸出字段分隔符(缺省爲:space:)
awk -F ':' 'BEGIN{OFS=";"}{print $1,$2,$3}' b
若是cat b爲
1:2:3
4:5:6
那麼把OFS設置成";"後就會輸出
1;2;3
4;5;6
(小注釋:awk把分割後的第一、二、3個字段用$1,$2,$3...表示,$0表示整個記錄(通常就是一整行))
NF:當前記錄中的字段個數
awk -F ':' '{print NF}' b的輸出爲
3
3
代表b的每一行用分隔符":"分割後都3個字段
能夠用NF來控制輸出符合要求的字段數的行,這樣能夠處理掉一些異常的行
awk -F ':' '{if (NF == 3)print}' b
RS:輸入記錄分隔符,缺省爲"\n"
缺省狀況下,awk把一行看做一個記錄;若是設置了RS,那麼awk按照RS來分割記錄
例如,若是文件c,cat c爲
hello world; I want to go swimming tomorrow;hiahia
運行 awk 'BEGIN{ RS = ";" } {print}' c 的結果爲
hello world
I want to go swimming tomorrow
hiahia
合理的使用RS和FS可使得awk處理更多模式的文檔,例如能夠一次處理多行,例如文檔d cat d的輸出爲
1 2
3 4 5
6 7
8 9 10
11 12
hello
每一個記錄使用空行分割,每一個字段使用換行符分割,這樣的awk也很好寫
awk 'BEGIN{ FS = "\n"; RS = ""} {print NF}' d 輸出
2
3
1
ORS:輸出記錄分隔符,缺省爲換行符,控制每一個print語句後的輸出符號
awk 'BEGIN{ FS = "\n"; RS = ""; ORS = ";"} {print NF}' d 輸出
2;3;1
運算符 |
描述 |
= += -= *= /= %= ^= **= |
賦值 |
?: |
C條件表達式 |
|| |
邏輯或 |
&& |
邏輯與 |
~ ~! |
匹配正則表達式和不匹配正則表達式 |
< <= > >= != == |
關係運算符 |
空格 |
鏈接 |
+ - |
加,減 |
* / & |
乘,除與求餘 |
+ - ! |
一元加,減和邏輯非 |
^ *** |
求冪 |
++ -- |
增長或減小,做爲前綴或後綴 |
$ |
字段引用 |
in |
數組成員 |
6.1. 記錄
awk把每個以換行符結束的行稱爲一個記錄。
記錄分隔符:默認的輸入和輸出的分隔符都是回車,保存在內建變量ORS和RS中。
$0變量:它指的是整條記錄。如$ awk '{print $0}' test將輸出test文件中的全部記錄。
變量NR:一個計數器,每處理完一條記錄,NR的值就增長1。
如$ awk '{print NR,$0}' test將輸出test文件中全部記錄,並在記錄前顯示記錄號。
6.2. 域
記錄中每一個單詞稱作「域」,默認狀況下以空格或tab分隔。awk可跟蹤域的個數,並在內建變量NF中保存該值。如$ awk '{print $1,$3}' test將打印test文件中第一和第三個以空格分開的列(域)。
6.3. 域分隔符
內建變量FS保存輸入域分隔符的值,默認是空格或tab。咱們能夠經過-F命令行選項修改FS的值。如$ awk -F: '{print $1,$5}' test將打印以冒號爲分隔符的第一,第五列的內容。
能夠同時使用多個域分隔符,這時應該把分隔符寫成放到方括號中,如$awk -F'[:/t]' '{print $1,$3}' test,表示以空格、冒號和tab做爲分隔符。
輸出域的分隔符默認是一個空格,保存在OFS中。如$ awk -F: '{print $1,$5}' test,$1和$5間的逗號就是OFS的值。
用來在記錄或者域內匹配正則表達式。如$ awk '$1 ~/^root/' test將顯示test文件第一列中以root開頭的行。
conditional expression1 ? expression2: expression3,
例如:
$ awk '{max = {$1 > $3} ? $1: $3: print max}' test。若是第一個域大於第三個域,$1就賦值給max,不然$3就賦值給max。
$ awk '$1 + $2 < 100' test。若是第一和第二個域相加小於100,則打印這些行。
$ awk '$1 > 5 && $2 < 10' test,若是第一個域大於5,而且第二個域小於10,則打印這些行。
範圍模板匹配從第一個模板的第一次出現到第二個模板的第一次出現之間全部行。若是有一個模板沒出現,則匹配到開頭或末尾。如$ awk '/root/,/mysql/' test將顯示root第一次出現到mysql第一次出現之間的全部行。