使用awk提取文本

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.

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章