1案例1:使用awk提取文本
1.1問題
本案例要求使用awk工具完成下列過濾任務:
- 練習awk工具的基本用法
- 提取本機的網卡流量、根分區剩餘容量、獲取ssh遠程失敗的IP地址
- 格式化輸出/etc/passwd文件中的用戶名、UID、宿主目錄信息
1.2步驟
實現此案例需要按照如下步驟進行。
步驟一:awk文本過濾的基本用法
1)基本操作方法
格式:awk [選項] '[條件]{指令}' 文件
其中,print是最常用的編輯指令;若有多條編輯指令,可用分號分隔。
awk過濾數據時支持僅打印某一列,如第2列、第5列等
處理文本時,若未指定分隔符,則默認將空格、製表符等作爲分隔符。
直接過濾文件內容:
[root@svr5 ~]# cat test.txt
hello the world
welcome to beijing
[root@svr5 ~]# awk '{print $1,$3}' test.txt //打印文檔第1列和第3列
hello world
welcome beijing
結合管道過濾命令輸出:
[root@svr5 ~]# df -h | awk '{print $4}' //打印磁盤的剩餘空間
2)選項-F可指定分隔符
輸出passwd文件中以分號分隔的第1、7個字段,顯示的不同字段之間以逗號隔開,操作如下:
[root@svr5 ~]# awk -F: '{print $1,$7}' /etc/passwd
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
lp /sbin/nologin
… …
awk還識別多種單個的字符,比如以":"或"/"分隔,輸出低1、10個字段:
[root@svr5 ~]# awk -F [:/] '{print $1,$10}' /etc/passwd
root bash
bin nologin
daemon nologin
adm sbin
… …
awk常用內置變量:
$0文本當前行的全部內容
$1文本的第1列
$2文本的第2列
$3文本的第3列,以此類推
NR文件當前行的行號
NF文件當前行的列數(有幾列)
輸出每次處理的行號,以及當前行以":"分隔的字段個數(有幾列):
[root@svr5 ~]# awk -F: '{print NR,NF}' passwd.txt
1 7
2 7
3 7
.. ..
3)awk的print指令不僅可以打印變量,還可以打印常量
[root@svr5 ~]# awk -F: '{print $1,"的解釋器:",$7}' /etc/passwd
root 的解釋器: /bin/bash
bin 的解釋器: /sbin/nologin
… …
步驟二:利用awk提取本機的網絡流量、根分區剩餘容量,獲取遠程失敗的IP地址
1)提取IP地址
分佈實現的思路及操作參考如下——
通過ifconfig eth0查看網卡信息,其中包括網卡流量:
[root@svr5 ~]# ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.4.21 netmask 255.255.255.0 broadcast 192.168.4.255
inet6 fe80::fa64:c143:ad6a:5159 prefixlen 64 scopeid 0x20<link>
ether 52:54:00:b3:11:11 txqueuelen 1000 (Ethernet)
RX packets 313982 bytes 319665556 (304.8 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 51809 bytes 40788621 (38.8 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
RX爲接受的數據量,TX爲發送的數據量。packet以數據包的數量爲單位,bytes以字節爲單位:
[root@svr5 ~]# ifconfig eth0 | awk '/RX p/{print $5}' //過濾接收數據的流量
319663094
[root@svr5 ~]# ifconfig eth0 | awk '/TX p/{print $5}' //過濾發送數據的流量
40791683
2)提取根分區剩餘容量
分佈實現的思路及操作參考如下——
通過df命令查看根分區的使用情況,其中包括剩餘流量:
[root@svr5 ~]# df -h /
文件系統 容量 已用 可用 已用% 掛載點
/dev/sda2 19G 7.2G 11G 40% /
輸出上述結果中的最後一行的第四列:
[root@svr5 ~]# df -h / | tail -1 | awk '{print $4}'
11G
或者直接在awk中使用正則:
[root@svr5 ~]# df -h | awk '/\/$/{print $4}'
11G
3)根據/var/log/secure日誌文件,過濾遠程連接密碼失敗的IP地址
[root@svr5 ~]# awk '/Failed/{print $11}' /var/log/secure
192.168.2.254
192.168.2.100
... ...
步驟三:格式化輸出/etc/passwd文件
1)awk處理的時機
awk會逐行處理文件,支持在處理第一行之前做一些準備工作,以及在處理完最後一行之後做一些走總結性質的工作。在命令格式上分別體現如下:
awk [選項] '[條件]{指令}' 文件
awk [選項] ' BEGIN{指令} {指令} END{指令}' 文件
- BEGIN{}行前處理,讀取文件內容前執行,指令執行1次
- {}逐行處理,讀取文件過程中執行,指令執行n次
- END{}行後處理,讀取文件結束後執行,指令執行1次
只做預處理的時候,可以沒有操作文件,比如:
[root@svr5 ~]# awk 'BEGIN{A=24;print A*2}'
[root@svr5 ~]# awk 'BEGIN{print x+1}' #x可以不定義,直接用,默認值爲0
[root@svr5 ~]# awk 'BEGIN{print 3.2+3.5}'
舉個例子(統計系統中使用bash作爲登錄shell用戶總個數):
a.預處理時賦值變量x=0
b.然後逐行讀入/etc/passwd文件,如果發現登錄shell是/bin/bash則x加1
c.全部處理完畢後,輸出x的值即可。相關操作及結果如下:
[root@svr5 ~]# awk 'BEGIN{x=0}/bash$/{x++} END{print x}' /etc/passwd
29
2)格式化輸出/etc/passwd文件
要求:格式化輸出passwd文件內容時,要求第一行列表標題,中間打印用戶的名稱、UID、家目錄信息,最好一行提示一共處理文本的總行數,如圖所示:
3)根據實現思路編寫、驗證awk過濾語句
輸出信息時,可以使用"\t"顯示Tab製表位:
[root@svr5 ~]# awk -F: 'BEGIN{print "User\tUID\tHome"} \
{print $1 "\t" $3 "\t" $6} \
END{print "Total",NR,"lines."}' /etc/passwd
User UID Home
root 0 /root
bin 1 /bin
daemon 2 /sbin
adm 3 /var/adm
lp 4 /var/spool/lpd
sync 5 /sbin
.. ..
Total 67 lines.