1 awk 工作原理和基本用法說明
awk:Aho, Weinberger, Kernighan,報告生成器,格式化文本輸出,GNU/Linux釋出的AWK目前由自由軟體基金會(FSF)進行開發和維護,通常也稱它為 GNU AWK
有多種版本:
- AWK:原先來源于 AT & T 實驗室的的AWK
- NAWK:New awk,AT & T 實驗室的AWK的更新版
- GAWK:即GNU AWK。所有的GNU/Linux釋出版都自帶GAWK,它與AWK和NAWK完全相容
gawk:模式掃描和處理語言,可以實作下面功能
- 文本處理
- 輸出格式化的文本報表
- 執行算數運算
- 執行字元串操作
格式:
awk [options] 'program' var=value file…
awk [options] -f programfile var=value file…
說明:
program通常是被放在單引号中,并可以由三種部分組成
- BEGIN語句塊
- 模式比對的通用語句塊
- END語句塊
常見選項:
- -F “分隔符” 指明輸入時用到的字段分隔符,預設的分隔符是若幹個連續空白符
- -v var=value 變量指派
Program格式:
pattern{action statements;..}
pattern:決定動作語句何時觸發及觸發事件,比如:BEGIN,END,正規表達式等
action statements:對資料進行處理,放在{}内指明,常見:print, printf
awk 工作過程
第一步:執行BEGIN{action;… }語句塊中的語句
第二步:從檔案或标準輸入(stdin)讀取一行,然後執行pattern{ action;… }語句塊,它逐行掃描檔案,從第一行到最後一行重複這個過程,直到檔案全部被讀取完畢。
第三步:當讀至輸入流末尾時,執行END{action;…}語句塊BEGIN語句塊在awk開始從輸入流中讀取行之前被執行,這是一個可選的語句塊,比如變量初始化、列印輸出表格的表頭等語句通常可以寫在BEGIN語句塊中END語句塊在awk從輸入流中讀取完所有的行之後即被執行,比如列印所有行的分析結果這類資訊彙總都是在END語句塊中完成,它也是一個可選語句塊pattern語句塊中的通用指令是最重要的部分,也是可選的。如果沒有提供pattern語句塊,則預設執行{print },即列印每一個讀取到的行,awk讀取的每一行都會執行該語句塊
分割符、域和記錄
- 由分隔符分隔的字段(列column,域field)标記$1,$2...$n稱為域辨別,$0為所有域,注意:和shell中變量$符含義不同
- 檔案的每一行稱為記錄record
- 如果省略action,則預設執行 print $0 的操作
常用的action分類
- output statements:print,printf
- Expressions:算術,比較表達式等
- Compound statements:組合語句
- Control statements:if, while等
- input statements
awk控制語句
- { statements;… } 組合語句
- if(condition) {statements;…}
- if(condition) {statements;…} else {statements;…}
- while(conditon) {statments;…}
- do {statements;…} while(condition)
- for(expr1;expr2;expr3) {statements;…}
- break
- continue
- exit
1.1 動作 print
格式:
print item1, item2, ...
說明:
- 逗号分隔符
- 輸出item可以字元串,也可是數值;目前記錄的字段、變量或awk的表達式
- 如省略item,相當于print $0
- 固定字元符需要用“ ” 引起來,而變量和數字不需要
#輸入指令後按回車,不想繼續就按ctrl+c中斷
[root@nginx ~]# awk '{print "hello,akw"}'
hello,akw
hello,akw
^C
#列印出兩行hello,awk
[root@nginx ~]# seq 2 | awk '{print "hello,awk"}'
hello,awk
hello,awk
#列印3個6
[root@nginx ~]# seq 3 | awk '{print 2*3}'
6
6
6
#列印passwd檔案的内容
[root@nginx ~]# awk -F: '{print}' /etc/passwd
#列印passwd檔案的1,3列
[root@nginx ~]# awk -F: '{print $1,$3}' /etc/passwd
[root@nginx ~]#awk -F: '{print $1"\t"$3}' /etc/passwd
[root@nginx ~]# grep "^UUID" /etc/fstab |awk {'print $2,$3'}
/boot xfs
[root@nginx ~]# grep "^UUID" /etc/fstab
UUID=d0727353-4fcc-4e63-802d-86f45ff1d3ad /boot xfs defaults 0 0
[root@nginx ~]#
案例:取出分區使用率
[root@nginx ~]# df | awk '{print $1,$5}'
檔案系統 已用%
/dev/mapper/centos-root 3%
devtmpfs 0%
tmpfs 0%
tmpfs 1%
tmpfs 0%
/dev/sda1 33%
tmpfs 0%
[root@nginx ~]#
#使用擴充的正規表達式
[root@nginx ~]# df | awk -F"[[:space:]]+|%" '{print $5}'
已用
3
0
0
1
0
33
0
[root@nginx ~]# df | grep "^/dev/sd" | awk -F"[[:space:]]+|%" '{print $5}'
33
[root@nginx ~]# df | grep '^/dev/sd'| awk -F'[[:space:]]+|%' '{print $1,$5}'
/dev/sda1 33
[root@nginx ~]# df | awk -F"[[:space:]]+|%" '/^\/dev\/sd/{print $5}'
33
[root@nginx ~]# df | awk -F'[[:space:]]+|%' '/^\/dev\/sd/{print $1,$5}'
/dev/sda1 33
[root@nginx ~]# df|awk -F' +|%' '/^\/dev\/sd/{print $1,$5}'
/dev/sda1 33
[root@nginx ~]#
案例:取 ifconfig 輸出結果中的IP位址
[root@nginx ~]# hostname -I | cat -A
192.168.223.111 $
[root@nginx ~]#
[root@nginx ~]# ifconfig ens33|sed -n '2p' |awk '{print $2}'|cat -A
192.168.223.111$
[root@nginx ~]# ifconfig ens33 | awk '/netmask/{print $2}'
192.168.223.111
[root@nginx ~]# ip a show ens33 |awk -F' +|\/' '/\<inet\>/{print $3}' 2>/dev/null
192.168.223.111
[root@nginx ~]# ifconfig ens33 |awk -F " +|:" '/mask/{print $3}'
192.168.223.111
[root@nginx ~]# ifconfig ens33| sed -rn '2s/^[^0-9]+([0-9.]+) .*$/\1/p'
192.168.223.111
[root@nginx ~]
1.2 awk 變量
awk中的變量分為:内置和自定義變量
1.2.1 常見的内置變量
FS:輸入字段分隔符,預設為空白字元,功能相當于 -F
案例:
[root@nginx ~]# awk -v FS=':' '{print $1,FS,$3}' /etc/passwd
[root@nginx ~]# awk -v FS=":" '{print $1FS$3}' /etc/passwd
[root@nginx ~]# awk -F: '{print $1,$3,$7}' /etc/passwd
[root@nginx ~]# S=:;awk -v FS=$S '{print $1FS$3}' /etc/passwd
[root@nginx ~]# awk -v FS=":" '{print $1FS$3}' /etc/passwd |head -n3
root:0
bin:1
daemon:2
[root@nginx ~]# S=:;awk -F$S '{print $1,$3}' /etc/passwd|head -n3
root 0
bin 1
daemon 2
[root@nginx ~]#
#-F 和 FS變量功能一樣,同時使用會沖突
[root@nginx ~]# awk -v FS=":" -F";" '{print $1FS$3}' /etc/passwd |head -n3
root:x:0:0:root:/root:/bin/bash;
bin:x:1:1:bin:/bin:/sbin/nologin;
daemon:x:2:2:daemon:/sbin:/sbin/nologin;
[root@nginx ~]# awk -F";" -v FS=":" '{print $1FS$3}' /etc/passwd |head -n3
root:0
bin:1
daemon:2
#-F 和 FS變量功能一樣,同時使用 -F 優先級高
[root@nginx ~]# awk -v FS=":" -F";" '{print $1}' /etc/passwd |head -n3
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
[root@nginx ~]# awk -v FS=";" -F":" '{print $1}' /etc/passwd |head -n3
root
bin
daemon
[root@nginx ~]#
- OFS:輸出字段分隔符,預設為空白字元
案例:
[root@nginx ~]# awk -v FS=':' '{print $1,$3,$7}' /etc/passwd|head -n1
root 0 /bin/bash
[root@nginx ~]#
[root@nginx ~]# awk -v FS=':' -v OFS=':' '{print $1,$3,$7}' /etc/passwd|head -n1
root:0:/bin/bash
[root@nginx ~]#
- RS:輸入記錄record分隔符,指定輸入時的換行符
案例:
[root@nginx ~]#awk -v RS=' ' '{print }' /etc/passwd
- ORS:輸出記錄分隔符,輸出時用指定符号代替換行符
案例:
[root@nginx ~]# awk -v RS=' ' -v ORS='###' '{print $0}' /etc/passwd
- NF:字段數量
案例:
#引用變量時,變量前不需加$
[root@nginx ~]# awk -F: '{print NF}' /etc/fstab
[root@nginx ~]# awk -F: '{print $(NF-1)}' /etc/passwd
- NR:記錄的編号
案例:
[root@nginx ~]# awk '{print NR,$0}' /etc/issue /etc/centos-release
1 \S
2 Kernel \r on an \m
3
4 CentOS Linux release 7.5.1804 (Core)
[root@nginx ~]#
- FNR:各檔案分别計數,記錄的編号
案例:
[root@nginx ~]# awk '{print FNR}' /etc/fstab /etc/inittab
- FILENAME:目前檔案名
案例:
[root@nginx ~]# awk '{print FILENAME}' /etc/fstab
[root@nginx ~]# awk '{print FNR,FILENAME,$0}' /etc/issue /etc/redhat-release
1 /etc/issue \S
2 /etc/issue Kernel \r on an \m
3 /etc/issue
1 /etc/redhat-release CentOS Linux release 7.5.1804 (Core)
[root@nginx ~]#
- ARGC:指令行參數的個數
案例:
[root@nginx ~]# awk '{print ARGC}' /etc/issue /etc/redhat-release
3
3
3
3
[root@nginx ~]# awk 'BEGIN{print ARGC}' /etc/issue /etc/redhat-release
3
[root@nginx ~]#
1.2.2 自定義變量
自定義變量是區分字元大小寫的,使用下面方式進行指派
- -v var=value
- 在program中直接定義
案例:
[root@nginx ~]# awk -v test1=test2="hello,gawk" 'BEGIN{print test1,test2}'
test2=hello,gawk
[root@nginx ~]#
[root@nginx ~]# awk -v test1=test2="hello1,gawk" 'BEGIN{test1=test2="hello2,gawk";print test1,test2}'
hello2,gawk hello2,gawk
[root@nginx ~]#
[root@nginx ~]# awk -v test='hello gawk' '{print test}' /etc/fstab
[root@nginx ~]# awk -v test='hello gawk' 'BEGIN{print test}'
[root@nginx ~]# awk 'BEGIN{test="hello,gawk";print test}'
[root@nginx ~]# awk -F: '{sex="male";print $1,sex,age;age=18}' /etc/passwd
未完待續。。。