天天看點

Linux-文本處理三劍客之awk(一)

作者:不寐旋律

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 工作過程

Linux-文本處理三劍客之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           

未完待續。。。