一倔韭、awk簡介
awk 是一種編程語言航棱,用于在linux/unix下對文本和數(shù)據(jù)進(jìn)行處理虹菲。
數(shù)據(jù)可以來自標(biāo)準(zhǔn)輸入靠胜、一個或多個文件,或其它命令的輸出毕源。
支持用戶自定義函數(shù)和動態(tài)正則表達(dá)式等先進(jìn)功能浪漠,是linux/unix
下的一個強(qiáng)大編程工具。
在命令行中使用霎褐,但更多是作為腳本來使用址愿。
awk的處理文本和數(shù)據(jù)的方式是這樣的,它逐行掃描文件冻璃,從第一行到最后一行响谓,尋找匹配的特定模式的行损合,并在這些行上進(jìn)行你想要的操作。如果沒有指定處理動作娘纷,則把匹配的行顯示到標(biāo)準(zhǔn)輸出(屏幕)嫁审,如果沒有指定模式,則所有被操作所指定的行都被處理赖晶。
awk分別代表其作者姓氏的第一個字母律适。因為它的作者是三個人,分別是Alfred Aho遏插、Brian Kernighan捂贿、Peter Weinberger。
gawk是awk的GNU版本胳嘲,它提供了Bell實驗室和GNU的一些擴(kuò)展厂僧。
二、awk的兩種形式語法格式
awk [options] 'commands' filenames
awk [options] -f awk-script-file filenames
options:
-F
對于每次處理的內(nèi)容胎围,可以指定一個子定義的分隔符吁系,默認(rèn)的分隔符是空白字符(空格或 tab 鍵 )
command:
BEGIN{} {} END{}
處理所有內(nèi)容之前的動作 處理內(nèi)容中的動作 處理所有內(nèi)容之后的動作
示例
awk 'BEGIN{print "----開始處理了---"} {print "ok"} END{print "----都處理完畢---"}' /etc/hosts
----開始處理了---
ok
ok
ok
----都處理完畢---
BEGIN{}
通常用于定義一些變量,例如 BEGIN{FS=":";OFS="---"}
========================================================
三白魂、awk工作原理
awk -F: '{print $1,$3}' /etc/passwd
(1)awk汽纤,會處理文件的每一個行,每次處理時福荸,使用一行作為輸入蕴坪,并將這一行賦給內(nèi)部變量$0,每一行也可稱為一個記錄敬锐,以換行符結(jié)束
(2)然后背传,行被:(默認(rèn)為空格或制表符)分解成字段(或稱為域),每個字段存儲在已編號的變量中台夺,從$1開始径玖,
最多達(dá)100個字段
(3)awk如何知道用空白字符來分隔字段的呢? 因為有一個內(nèi)部變量FS來確定字段分隔符颤介。初始時梳星,F(xiàn)S賦為空白字符
(4)awk打印字段時,將以內(nèi)置的方法使用 print
函數(shù)打印滚朵,awk 在打印出的字段間加上空格冤灾。這個空格是內(nèi)部的一個變量 OFS
輸出字段的分隔符, 逗號 ,
會和 OFS
進(jìn)行映射,通過 OFS
可以控制這個輸出分隔符的值辕近。
(5)awk輸出之后韵吨,將從文件中獲取另一行,并將其存儲在$0中移宅,覆蓋原來的內(nèi)容归粉,然后將新的字符串分隔成字段并進(jìn)行處理椿疗。該過程將持續(xù)到所有行處理完畢
========================================================
四、記錄與字段相關(guān)內(nèi)部變量:
man awk
$0
: awk變量$0
保存當(dāng)前正在處理的行內(nèi)容
NR
: 當(dāng)前正在處理的行是 awk 總共處理的行號盏浇。
FNR
: 當(dāng)前正在處理的行在其文件中的行號变丧。
NF
:每行被處理時的總字段數(shù)
FS
: 輸入行時的字段分隔符,默認(rèn)空格awk 'BEGIN{FS=":"} {print $1,$3}' /etc/passwd
OFS
: 輸出字段分隔符,默認(rèn)是一個 空格awk 'BEGIN{FS=":"; OFS="+++"} /^root/{print $1,$2,$3,$4}' /etc/passwd
ORS
輸出記錄分隔符, 默認(rèn)是換行符.
示例
將文件每一行合并為一行
ORS默認(rèn)輸出一條記錄應(yīng)該回車绢掰,但是這里是加了一個空格
awk 'BEGIN{ORS=" "} {print $0}' /etc/passwd
五痒蓬、格式化輸出:
printf 函數(shù)
awk -F: '{printf "%-15s %-10s %-15s\n", $1,$2,$3}' /etc/passwd
awk -F: '{printf "|%-15s| %-10s| %-15s|\n", $1,$2,$3}' /etc/passwd
-
%s
字符類型 -
%d
十進(jìn)制整數(shù) -
%f
浮點類型 -
%-15s
占15字符-
表示左對齊,默認(rèn)是右對齊 -
printf
默認(rèn)不會在行尾自動換行滴劲,加\n
六攻晒、awk模式和動作
任何 awk
語句都由 模式 和 動作 組成。
模式部分
決定動作語句何時觸發(fā)及觸發(fā)事件班挖。
如果省略模式部分鲁捏,動作將時刻保持執(zhí)行狀態(tài)。
模式可以是任何條件語句或復(fù)合語句或正則表達(dá)式萧芙。
模式可以是
正則表達(dá)式:
- 匹配記錄(整行的匹配):
awk '/^root/' /etc/passwd
awk '$0 ~ /^root/' /etc/passwd
awk '!/root/' passwd
awk '$0 !~ /^root/' /etc/passwd
- 匹配字段:可以使用的匹配操作符(
~
和!~
)
awk -F: '$1 ~ /^alice/' /etc/passwd
awk -F: '$NF !~ /bash$/' /etc/passwd
- 比較表達(dá)式:
比較表達(dá)式采用對文本進(jìn)行比較给梅,只有當(dāng)條件為真,才執(zhí)行指定的動作双揪。
比較表達(dá)式使用關(guān)系運算符动羽,用于比較數(shù)字與字符串。關(guān)系運算符有
<
小于 例如x<y
>
大于x>y
<=
小于或等于x<=y
==
等于x==y
!=
不等于x!=y
>=
大于等于x>=y
示例
awk -F: '$3 == 0' /etc/passwd
awk -F: '$3 < 10' /etc/passwd
awk -F: '$NF == "/bin/bash"' /etc/passwd
awk -F: '$1 == "root"' /etc/passwd
df -P | grep '/' |awk '$4 > 25000'
- 條件表達(dá)式:
awk -F: '$3>300 {print $0}' /etc/passwd
awk -F: '{ if($3>300) print $0 }' /etc/passwd
awk -F: '{ if($3>300) {print $0} }' /etc/passwd
awk -F: '{ if($3>300) {print $3} else{print $1} }' /etc/passwd
- 算術(shù)運算:
+
,-
,*
,/
,%(模: 取余)
,^(冪:2^3)
可以在模式中執(zhí)行計算渔期,awk都將按浮點數(shù)方式執(zhí)行算術(shù)運算
awk -F: '$3 * 10 > 500' /etc/passwd
awk -F: '{ if($3*10>500){print $0} }' /etc/passwd
- 邏輯操作符和復(fù)合模式
&&
邏輯與, 相當(dāng)于 并且
||
邏輯或运吓,相當(dāng)于 或者
!
邏輯非 , 取反
awk -F: '$1~/root/ && $3<=15' /etc/passwd
awk -F: '$1~/root/ || $3<=15' /etc/passwd
awk -F: '!($1~/root/ || $3<=15)' /etc/passwd
? ~ cat passwd
root:x:0:0:root:/root:/bin/zsh
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:20:2:daemon:/sbin:/sbin/nologin
root:x:20:2:daemon:/sbin:/sbin/nologin
? ~ awk -F: '!($1~/root/ || $3<=15){print $0}' passwd
daemon:x:20:2:daemon:/sbin:/sbin/nologin
? ~ awk -F: '($1~/root/ || $3<=15){print $0}' passwd
root:x:0:0:root:/root:/bin/zsh
bin:x:1:1:bin:/bin:/sbin/nologin
root:x:20:2:daemon:/sbin:/sbin/nologin
- 范圍模式, 模式之間用逗號
,
隔開
使用語法是: 起始表達(dá)式, 終止表達(dá)式
下面的意思是: 從開頭是
bin
的行開始匹配成功一直到含有adm
的行結(jié)束匹配
也就是 開頭是bin
的行到含有adm
的行 的所有內(nèi)容都符合匹配條件。
? ~ awk -F: '/^bin/,/adm/ {print $0 }' /etc/passwd
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
awk 正則示例:
匹配開頭是
bin
的或者開頭是root
的行
? ~ awk -F: '/^(bin|root)/' /etc/passwd
root:x:0:0:root:/root:/bin/zsh
bin:x:1:1:bin:/bin:/sbin/nologin
指定多個分隔符:[]
? ~ echo "a b|c d| ||||e | |" |awk -F'[ |]' '{print $10}'
e
? ~ echo "a b|c d| ||||e | |" |awk -F'[ |]+' '{print $5}'
e
分隔符跟分隔符之間有一個字符
注意: 正則中疯趟,中括號內(nèi)的任意字符均視為普通字符拘哨, 比如
.
*
都被看做是 普通字符。
例如:$ echo "a.b*c" |awk -F'[.*]' '{print $1, $2,$3}' a b c
七信峻、awk 腳本編程
條件判斷
if語句
格式
{ if (表達(dá)式) {語句; 語句; ...}}
awk -F: '{if($3==0) {print $1 " is administrator."}}' /etc/passwd
awk -F: '{if($3>0 && $3<1000){count++;}} END{print count}' /etc/passwd
統(tǒng)計系統(tǒng)級別用戶的數(shù)量
if...else語句
格式
{if(表達(dá)式){語句;語句;...}else{語句;語句;...}}
awk -F: '{if($3==0){print $1} else {print $7}}' /etc/passwd
awk -F: '{if($3==0) {count++} else{i++} }' /etc/passwd
awk -F: '{ if($3==0){count++} else{i++} } END{print "管理員個數(shù): "count ; print "系統(tǒng)用戶數(shù): "i}' /etc/passwd
if...else if...else語句
格式
{if(表達(dá)式1) {語句;語句倦青;...} else if (表達(dá)式2) {語句;語句;...} else if(表達(dá)式3){語句;語句盹舞;...} else {語句;語句产镐;...} }
awk -F: '{if($3==0){i++} else if($3>999){k++} else{j++}} END{print i; print k; print j}' /etc/passwd
awk -F: '{if($3==0){i++} else if($3>999){k++} else{j++}} END{print "管理員個數(shù): "i; print "普通用個數(shù): "k; print "系統(tǒng)用戶: "j}' /etc/passwd
awk使用外部變量:
擴(kuò)展
方法一:awk參數(shù)-v(推薦使用,易讀)
[root@tianyun ~]# echo "unix script" |awk -v var="bash" 'gsub(/unix/,var)'
bash script
[root@tianyun ~]# awk -v user=root -F: '$1 == **user**' /etc/passwd
root:x:0:0:root:/root:/bin/bash
gsub
使 AWK 中的內(nèi)置函數(shù)矾策,功能使搜索替換
'gsub(/unix/,var)
中的意思是搜索unix
字符串,替換為 var 變量對應(yīng)的值
方法二:在雙引號的情況下使用
[root@tianyun ~]# var="bash"
[root@tianyun ~]# echo "unix script" |awk "gsub(/unix/,\"$var\")"
bash script
方法三:在單引號的情況下使用(逼不得已使用)
[root@tianyun ~]# var="bash"
[root@tianyun ~]# echo "unix script" |awk 'gsub(/unix/,"'"$var"'")'
bash script
其他練習(xí)
[root@tianyun ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/cl-root 2.8T 246G 2.5T 9% /
tmpfs 24G 20K 24G 1% /dev/shm
/dev/sda2 1014M 194M 821M 20% /boot
[root@tianyun ~]# df -h |awk '{ if(int($5)>5){print $6":"$5} }'
/:9%
/boot:20%
[root@tianyun ~]# i=10
[root@tianyun ~]# df -h |awk '{ if(int($5)>'''$i'''){print $6":"$5} }'
/boot:20%