二十八、awk
awk:流式編輯器,針對文檔的行進行操作。awk兼具sed的所有功能,且更強大。可以對每段做匹配,不能更改文件內容,不像sed有-i選項能更改內容。
截取文檔中的某段,示例:
-F:指定分隔符,若不加-F,則以空格或tab為分隔符。print為打印的動作,用來打印某個字段。$1為第一個字段,以此類推,$0表示整行。
# awk -F ':' {print $1} test.txt 打印第一段
# head -n2 test.txt |awk -F ':' '{print $1}' 打印前兩行的第一段
# head -n2 test.txt |awk -F ':' '{print $0}' 打印前兩行整行(所有段)
# awk -F ':' '{print $1,$2,$4}' test.txt 多打印幾段,用逗號隔開;也可用#,但是#麻煩一點,要用雙引號括起來,示例:
# awk -F ':' '{print $1"#"$2"#"$4}' test.txt
root#x#0
bin#x#1
daemon#x#2
# awk -F ':' '{print $0}' test.txt 打印所有行
不指定分隔符,示例:
# awk '{print $1}' 1.txt
1
aa
cc
# cat 1.txt
1 2
aa bb
cc d
匹配字符或字符串
# awk '/ot/' test.txt 指定字符為ot
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologi
# awk -F ':' '$1 ~/oo/' test.txt
root:x:0:0:root:/root:/bin/bash
精確匹配,第一段裏包含oo的行,1後加個~
# awk -F ':' '/root/ {print $1,$2} /user/ {print $1,$2}' test.txt 多次匹配
先匹配root,再匹配user。
條件操作符
邏輯符號判斷,==為等於,還有>、>=、<、<=、!=等,!=為不匹配。若把比較的數字用雙引號括起來,awk會認為是字符,不括起來會認為是數字。
# awk -F ':' '$3=="0"' test.txt
# awk -F ':' '$3>="0"' test.txt
# awk -F ':' '$3>=500' test.txt
匹配數字時就不要加雙引號,否則認為是字符
# awk -F ':' '$7!="/sbin/nologin"' test.txt 是字符串,所以要加上雙引號
# awk -F ':' '$3<$4' test.txt 兩個段之間進行邏輯比較,第三段小於第四段
||和&&,分別表示“或者”,“並且”。示例:
# awk -F ':' '$3<"4" && $3<"7"' test.txt
此處4和7代表字符,所以要用雙引號括起來。
# awk -F ':' '$3>1000 || $7=="/bin/bash"' test.txt
第三段大於1000,或者第七段等於/bin/bash的。
# awk -F ':' '$3>1000 || $7 ~ /bash/' test.txt
匹配第七段為bash的,或者第三段大於1000的。
awk的內置變量
awk常用變量:OFS、NF和NR。
OFS:和-F選項有類似的功能,也是用來定義分隔符的,但是它是在輸出的時候定義。
NF:表示用分隔符分隔後一共有多少段
NR:表示行號
OFS用法示例:
# head -n5 test.txt |awk -F ':' '{OFS="#"} {print $1,$3}'
定義分隔符為#,也可以定義為@
root#0
bin#1
daemon#2
adm#3
lp#4
更高級的用法,示例:
# awk -F ':' '{OFS="#"} {if ($3<1000) {print $1,$3,$4}}' /etc/passwd
if:如果,判斷的作用。如果$3<1000 則打印出 $1$3$4 ,輸出並以#分隔顯示。
NF用法示例:
# awk -F ':' '{print NF":" $0}' test.txt 顯示所有段有多少段。
# awk -F ':' 'NF==7 && $1 ~ /root|sync/' test.txt 配合匹配一起用
# head -n3 /etc/passwd |awk -F ':' '{print NF}'
7
7
7
# head -n3 /etc/passwd |awk -F ':' '{print $NF}'
/bin/bash
/sbin/nologin
/sbin/nologin
此處NF是多少段,$NF是最後一段的值。
NF:表示用分隔符分隔後一共有多少段
NR用法示例:
# awk -F ':' '{print NR":" $0}' test.txt 顯示所有段的行號
# head -n3 /etc/passwd |awk -F ':' '{print NR}'
1
2
3
# awk -F ':' 'NR<=10' test.txt 前十行,NR可作為判斷條件。
NR也可配合段匹配一起使用,示例:
# awk -F ':' 'NR<=10 && $1 ~ /root|sync/' test.txt
NR:表示行號
# awk -F ':' '{print $NR":"$NF}' test.txt 顯示出的內容將從$1開始往後推。
awk中的數學運算
awk可以更改段值,示例:
# head -n3 test.txt | awk -F ':' '$1="root"'
root x 0 0 root /root /bin/bash
root x 1 1 bin /bin /sbin/nologin
root x 2 2 daemon /sbin /sbin/nologin
# head -n3 test.txt | awk -F ':' '{OFS=":"} $1="root"'
root:x:0:0:root:/root:/bin/bash
root:x:1:1:bin:/bin:/sbin/nologin
root:x:2:2:daemon:/sbin:/sbin/nologin
此處是一個等於號,是賦值的意思,兩個等於號就是匹配出來的意思,要分清楚。可以看到前三行的第一段都變為了root。可以直接定義分隔符為“:”。
計算某個段的總和,示例:
# awk -F ':' '{(tot=tot+$3)}; END {print tot}' test.txt
4610
(表示每一行的第三段相加,最後再print求和)
END:awk特有語法,表示所有的行都執行。
if:判斷。
for:循環。
# awk -F ':' '{if ($1=="root") {print $0}}' test.txt
root:x:0:0:root:/root:/bin/bash
先判斷第一段有root的,再打印整行。
二十八、awk