首頁 > 軟體

Linux文字處理三劍客之gawk

2020-06-16 17:09:56

gawk程式是Unix中原始awk程式的GNU版本。gawk程式讓流編輯器邁上了一個新的台階,它提供了一種程式語言而不只是編輯器命令。在gawk程式語言中,可以完成下面的事情:
(1)定義變數來儲存資料;
(2)使用算數和字串操作符來處理資料;
(3)使用結構化程式設計概念(比如if-then語句和迴圈)來為資料處理增加處理邏輯;
(4)通過提取資料檔案中的資料元素,將其重新排列或格式化,生成格式化報表;
gawk程式的報告生成能力通常用來從大文字檔案中提取資料元素,並將它們格式化成可讀的報告。其中完美的例子是格式化紀錄檔檔案。在紀錄檔檔案中找出錯誤行會很難,gawk程式可以讓你從紀錄檔檔案中過濾出需要的資料元素,然後你可以將其格式化,使得重要的資料易於閱讀。

1 gawk命令格式

gawk option program file
    選項:     描述
    -F fs           指定行中劃分資料欄位的欄位分隔符
    -f file         從指定的檔案中讀取程式
    -v var=value        定義gawk程式中的一個變數及其預設值
    -mf N           指定要處理的資料檔案中的最大欄位數
    -mr N           指定資料檔案中的最巨量資料行數
    -W  keyword     指定gawk的相容模式或警告等級

命令列選項提供了一個簡單的途徑來客製化gawk程式中的功能。
gawk的強大之處在於程式指令碼,可以寫指令碼來讀取文字行的資料,然後處理並顯示資料,建立任何型別的輸出報告。

2 從命令列讀取程式指令碼

(1)gawk程式及指令碼用一對花括號來定義。你必須將命令放到兩個花括號“{}”中。如果你錯誤的使用了圓括號來包含gawk指令碼,就會出錯。
(2)由於gawk命令列假定指令碼是單個文字字串,你還必須將指令碼放到單引號中。
例如:

        [root@CentOS7 ~]# gawk '{print "Hello World!"}'

執行這個命令,你可能會有些失望,因為什麼都不會發生。原因在於沒有在命令列上指定檔名,所有gawk程式會從STDIN接受資料。在執行這個程式時,它會一直等待從STDIN輸入的文字。
如果你輸入一行文字並按下確認鍵,gawk會對這行文字執行一遍程式指令碼。跟sed編輯器一樣,gawk程式會針對資料流中的每一行文字執行程式。由於程式指令碼被設為顯示一行固定的文字字串,因此不管你在資料流中輸入什麼文字,都會得到同樣的文字輸出。

[root@centos7 ~]# gawk '{print "Hello World!"}'
Thie is a error test
Hello World!
Hello World!
Hello World!

要終止這個程式,你必須標明資料流已經結束了。bash shell提供了一個組合鍵倆生成EOF(End –of-File)字元。Ctrl + D 組合鍵會字bash中產生一個EOF字元。這個組合鍵能夠終止該gawk程式並返回到命令列介面提示符下。

3 使用資料欄位變數

gawk的主要特徵之一是其處理文字檔案中資料的能力。它會自動給一行的每個資料元素分配一個變數。預設情況下,gawk會將如下變數分配給它在文字中發現的資料欄位:

$0  代表整個文字行
$1  代表文字行的第一個資料段
$n  代表文字行的第n個資料段

在文字行中,每個資料段都是通過欄位分隔符劃分的。gawk在讀取一行文字時,會用預定義的欄位分隔符劃分每個欄位。gawk中預設的欄位分隔符是任意的空白字元(例如空格或者製表符)。
例如,用-F指定欄位分隔符。顯示系統密碼檔案的第一個資料欄位。由於/etc/passwd用冒號來分隔資料欄位,因而可以將冒號指定為欄位分隔符。

[root@centos7 ~]# gawk -F : '{print $1}' /etc/passwd
root
bin
daemon
adm
lp
sync
shutdown
halt
mail
operator
[……]

4 在程式指令碼中使用多個命令

gawk程式語言允許將多條命令組合成一個正常程式。要在命令列上的程式指令碼中使用多條命令,只要在命令之間放個分號即可。
例如

[root@centos7 ~]# echo "My name is centos"|gawk '{$4="hahaha";print $0}'
My name is hahaha

第一條命令會給$4賦值。第二條命令會列印整個資料欄位。注意,gawk程式在輸出中已經將原文字中的第四個資料欄位替換了新值。

5 從文字中讀取程式

跟sed編輯器一樣,gawk編輯器允許將程式儲存到檔案中,然後再在命令列中參照。

[root@centos7 ~]# cat script2.gawk 
{print $1 "'s' home directory is " $6}
[root@centos7 ~]# gawk -F: -f script2.gawk  /etc/passwd
root's' home directory is /root
bin's' home directory is /bin
daemon's' home directory is /sbin
adm's' home directory is /var/adm
lp's' home directory is /var/spool/lpd
sync's' home directory is /sbin
shutdown's' home directory is /sbin
halt's' home directory is /sbin
mail's' home directory is /var/spool/mail
[……]

script2.gawk程式指令碼會再次使用print命令列印/etc/passwd檔案中的主目錄資料欄位(欄位變數$6),以及userID資料欄位(欄位變數$1)。
可以在程式檔案中指定多條命令。要這麼做的話,只有一天命令放一行即可,不需要使用分號。

[root@centos7 ~]# cat script3.gawk 
{
text = "'s home directory is "
print $1 text $6
}
[root@centos7 ~]# gawk -F: -f script3.gawk /etc/passwd
root's home directory is /root
bin's home directory is /bin
daemon's home directory is /sbin
adm's home directory is /var/adm
lp's home directory is /var/spool/lpd
sync's home directory is /sbin
shutdown's home directory is /sbin
[……]

script3.gawk程式指令碼定義了一個變數來儲存print命令中用到的文字字串。
注意:gawk程式在參照變數值時並未像shell指令碼一樣使用美元符。

6 在處理資料前執行指令碼

gawk還允許指定程式指令碼何時執行。預設情況下,gawk會從輸入中讀取一行文字,然後針對該行的資料執行程式指令碼。有時可能會需要在處理資料前執行指令碼,比如報告建立標題。BEGIN關鍵字就是用來做這個的。它會強制gawk在讀取資料前執行BEGIN關鍵字後指定的程式指令碼。

[root@centos7 ~]# cat data3.txt 
Line 1
Line 2
Line 3
[root@centos7 ~]# gawk 'BEGIN{print "The data3 File contents:"}{print $0}' data3.txt The data3 File contents:
Line 1
Line 2
Line 3

在gawk執行了BEGIN指令碼後,它會用第二段指令碼來處理檔案資料。這麼做是要小心,兩段指令碼仍然被認為是gawk命令列中的一個文字字串。你需要相應的加上單引號。

7 在處理資料後執行指令碼

與BEGIN關鍵字類似,END關鍵字允許你指定一個程式指令碼,gawk會在讀完資料後執行它。

[root@centos7 ~]# gawk '{print $0} END{print "End of file"}' data3.txt 
Line 1
Line 2
Line 3
End of file

當gawk程式列印完檔案內容後,會執行END指令碼中的命令。這是在處理完所有正常資料後給報告新增頁尾的最佳方法。

本文永久更新連結地址http://www.linuxidc.com/Linux/2017-07/145880.htm


IT145.com E-mail:sddin#qq.com