1.awk命令
awk的設計使得他非常適合處理由行列組成的文本數據。awk還是一種編程語言環境,他提供了正則表達式的匹配,流程控制,運算符,表達式,變量,以及函數等一系列的程序設計語言所具備的特性。
2.awk命令的基本語法
awk命令的基本語法:
awk 匹配模式 { 執行的操作 }
2.1 awk的工作流程
awk處理數據時,他會反覆執行一下4個步驟:
1.自動的從數據文件中讀取文本的行。
2.自動更新 awk 的內置系統變量的值。例如:列數變量NF,行數變量NR,行變量$0,各個變量$1,$2等。
3.依次執行程序中的所有的匹配模式及其操作。
4.當執行完程序的所有匹配模式和操作後,如果數據文件中仍有未讀取的數據行,則返回第一步重複執行1~4的操作。
2.2 awk的執行方式
用戶通過3種方式來執行awk程序,分別是命令行,awk腳本,可執行文件。
命令行語法 awk 'awk程序語句' 待處理的文件 。例如:awk '{ print }' a.txt
awk腳本語法 awk -f awk腳本 待處理的文件 。awk腳本里依次寫上awk程序語句即可。
可執行腳本語法 awk腳本 待處理的文件 。但是一定要指定命令解釋器 #! /bin/awk -f 。腳本內容依次寫上awk的程序語句即可。
2.3 特殊字符
$0:表示整個當前行
$1:每行第一個字段
NF:字段數量變量
NR:每行的記錄號,多文件記錄遞增
FNR:與NR類似,不過多文件記錄不遞增,每個文件都從1開始
FS:BEGIN時定義分隔符,默認是空格或製表符。
RS:輸入的記錄分隔符,默認是換行符。awk每次讀取一行進行處理,通過指定行分隔符,來決定awk一次讀取多少行。例如:指定行分隔符爲空行,awk每次讀取有空格的地方。
\t:製表符
\n:換行符
~ :匹配,與==相比不是精確比較
!~:不匹配,不精確比較
== :等於,必須全部相等,精確比較
!= :不等於,精確比較
&&:邏輯與
||: 邏輯或
+:匹配時表示1個或1個以上
/[0-9][0-9]+/: 兩個或兩個以上數字
/[0-9][0-9]*/ : 一個或一個以上數字
OFS:輸出字段分隔符, 默認也是空格,可以改爲製表符等
ORS:輸出的記錄分隔符,默認爲換行符,即處理結果也是一行一行輸出到屏幕
-F ':' :指定分隔符
3.awk的模式匹配
awk的匹配模式主要包括關係表達式,正則表達式,混合模式,BEGIN模式,END模式等。
3.1 關係表達式
awk提供了許多關係運算符,例如大於> ,小於< ,等於==等,awk可以以關係表達式作爲匹配模式,當文本行滿足關係表達式時,則會執行響應的操作。
實例:
顯示第二段大於80的行。
# awk '$2 > 80 { print }' 1.txt
q 90
e 86
r 84
y 98
表示第二列的值大於80,執行花括號裏面的 print 操作。
3.2 正則表達式
awk支持正則表達式匹配,和sed一樣,需要放在兩條斜線 /xx/ 之間。
實例:
# awk '/^(w|r)/ { print }' 1.txt
w 75
r 84
表示匹配w或r 並 print 出來。
3.3 混合模式
awk支持關係表達式和正則表達式,同時支持使用邏輯運算符。
&&:邏輯與
||:邏輯或
!:邏輯非
實例:
# awk '/^w/ && $2 > 70 { print }' 1.txt
w 75
兩條匹配模式都爲真,纔會顯示。
# awk '/^w/ || /^r/ { print }' 1.txt
w 75
r 84
兩條匹配模式哪條爲真顯示哪條。都爲真都顯示。
3.4 區間模式
區間模式是顯示兩條匹配模式之間的文本行。格式如下:
匹配模式1, 匹配模式2
實例:
匹配root開頭的行和UID爲3之間的行。-F指定分隔符。
# awk -F ":" '/^root/, $3==3 { print }' passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
3.5 BEGIN模式
BEGIN模式是一種內置的模式,該模式裏的內容生命週期只會被執行一次,一般用在腳本里面。語法如下:
#! /bin/awk -f
BEGIN {
執行的操作1
執行的操作2
...
}
{ 對待處理的文件執行的操作 }
寫成一行就是:
awk 'BEGIN { 執行的操作1; 執行的操作2; } { 對待處理的文件執行的操作 }' 待處理的文件
實例:
只使用BEGIN模式顯示內容。
# awk 'BEGIN { print "aaa"; print "=======" }'
aaa
=======
使用BEGIN模式同時文件進行操作。
# awk 'BEGIN { print "aaa"; print "=======" } { print }' 1.txt
aaa
=======
q 90
w 75
e 86
3.6 END模式
END模式也生命週期只會執行一次。一般會把善後的工作放在END模式對應模塊裏。在執行END模塊之前,必須執行操作或者執行BEGIN模式, 語法如下:
#! /bin/awk -f
{ 對待處理的文件執行的操作 }
END {
執行的操作1
執行的操作2
...
}
寫成一行就是:
awk ' { 對待處理的文件執行的操作 } END { 執行的操作1; 執行的操作2; }' 待處理的文件
實例:
執行END模式,前面必須有操作,不然不能執行。
# awk '{ print } END { print "aaa"; print "=======" }' 1.txt
q 90
w 75
e 86
aaa
=======
執行BEGIN模式和END模式
# awk 'BEGIN { print "aaa"; print "=======" } END { print "======="; print "aaa" }' 1.txt
aaa
=======
=======
aaa
4. 變量
awk的變量包括自定義的變量和系統內置變量。
4.1 自定義變量和引用
要放在BEGIN模式裏面,不然不會執行成功。引用變量直接跟變量名即可。
# awk 'BEGIN { x=3; print x }'
3
4.2 系統內置變量
4.3 內置變量行分隔符FS 字段分隔符RS
awk對文本進行處理是一行一行選取的,然後對文本行進行處理。
因爲系統變量FS默認的分隔符是換行符“\n”,如果更改換行符則會每次讀取到換行符的位置。
一般把 FS 和 RS 放在BEGIN 模塊裏面。
實例1:
指定A爲分割符,所以在處理後的A都換行符,而不出現了。
ccc下面的空格是文件本身的換行符\n。
# cat 1.txt
aaaAbbbAccc
# awk '{ print } { print "===="}' 1.txt //正常顯示
aaaAbbbAccc
====
# awk 'BEGIN { RS="A" } { print }{ print "===="}' 1.txt //指定RS之後
aaa
====
bbb
====
ccc
====
實例2:
把A當做字段分割符,顯示第一段,則第一個A前面的內容爲第一個字段符。
# cat 1.txt
a a a A b b b A c c c
# awk '{ print $1 }' 1.txt //正常顯示
a
# awk 'BEGIN { FS="A" } { print $1 }' 1.txt //指定FS之後。空格不再是分隔符了。
a a a
實例3:
匹配第三段大於500的行,print 第137段,分隔符用#。
# awk -F ":" '$3>500 { print $1"#"$3"#"$7}' test.txt
nfsnobody#4294967294#/sbin/nologin
mysql#501#/sbin/nologin
# awk -F ":" '{OFS="#"}$3>500 { print $1,$3,$7}' test.txt
nfsnobody#4294967294#/sbin/nologin
mysql#501#/sbin/nologin
4.4 記錄$0 ,字段$n 的引用
在awk中,用戶可以使用系統變量引用記錄和字段。
雖然awk每次讀取的是一行,但在程序中記錄和字段的引用都是針對當前整個文件或數據流來說的。也就是如果要顯示第一段會顯示整個文件的第一段。
實例1:
變量$0的值就是當前的記錄值,可以說是當前文件或者數據流的內容。
# awk '{ print $0 }' 1.txt
wang 85 92 79 87
li 89 90 73 82
zhao 81 88 92 81
實例2:
$1 $2 $3 分別代表第一列 第二列 第三列的數值。可以使用變量把數值的值相加。
# awk '{ print $1, $2+$3+$4+$5}' 1.txt
wang 343
li 334
zhao 342
5.運算符和表達式
5.1 算術運算符
實例:
# awk ' BEGIN { print 3^2 , 5%2 , 5/2 , 2*3 } '
9 1 2.5 6
5.2 賦值運算
實例:
# awk ' BEGIN { print x=5 , x+=5 , x%=6 , x*=3 } '
5 10 4 12
5.3 條件運算符
即當表達式的值爲真時,返回數值1,否則返回數值2。語法如下:
變量=(表達式?"數值1":"數值2")
print 變量
實例:
判斷打印成績單中的數值是否大於85,大於90的給A,否則給B。
# awk '{ a=($2>85?"A":"B"); print a }' 1.txt
B
A
B
# awk '{ a=($2>85?"A":"B"); print $1,a }' 1.txt
wang B
li A
zhao B
5.4 邏輯運算符
awk支持3種邏輯運算,分別是邏輯與,邏輯或和邏輯非。
實例:
當所有字段的數值都大於80時,才顯示出來。
# awk '$2 > 80 && $3 > 80 && $4 > 80 && $5 > 80 { print } ' 1.txt
zhao 81 88 92 81
5.5 關係運算
awk支持關係運算一般有:大於,小於,等於 等..
匹配運算符~ 不匹配運算符!~是awk特有的關係運算符,語法如下:
字符串 ~ 表達式
字符串 !~ 表達式
匹配運算符:判斷字符串中是否包含表達式的字符串。
不匹配運算符:判斷字符串中是否不包含表達式的字符串。
實例:
匹配第一個字符l開頭的記錄。
# awk '$1~/^l/ { print }' 1.txt
li 89 90 73 82
匹配前十行,第一段包含是root或者lp的行
# awk -F ":" 'NR<=10 && $1 ~ /root|lp/' test.txt
root:x:0:0:root:/root:/bin/bash
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin