251 瀏覽數

Linux command – awk 的程式結構

透過 sed 與 awk 都可以把文件做過濾和轉換成新的輸出內容.不過 sedhttp://benjr.tw/97129 適合用於一整行的資料處理,而 awk 則比較適合將一整行做多個 欄位(Field) 的資料處理.先來看看 awk 的幾個範例.

# mawk  [-W  option]  [-F value] [-v var=value] [--] 'program text' [file...]

awk 是 mawk 的連結,兩種方式都可以下指令.

awk 的 程式結構 (Program structure) 可以是一連串的 pattern {action} (條件類型1{動作1}) .
pattern 可以是:

  • BEGIN
  • END
  • expression
  • expression , expression

BEGIN{}

awk 在執行時就會先把第一行的資料讀取進來等待處理,所以有些定義必須透過 BEGIN{} 在這個之前先定義好時,BEGIN {} 所定義的內容只會執行一次.

root@ubuntu:~# awk 'BEGIN{FS=":"} {print "User:\t"$1}' /etc/passwd
User:	root
User:	daemon
User:	bin
User:	sys
User:	sync

沒有定義 BEGIN 時,會發現第一行沒有處理到.

END{}

END {} 只會在最後時執行一次.

root@ubuntu:~# awk 'END{print "Filename:" FILENAME , "\tCurrent Line:" FNR }' /etc/passwd 
Filename:/etc/passwd                     Current Line:41

沒有 END 時,Print 會列印出每一行處理的資料,使用 END 時只會在資料讀取處理完畢後,執行一次.

範例:顯示檔案數目

root@ubuntu:~# ls -laR |grep "^-" |awk 'END{print "Number of files."NR}'
Number of files.17

範例:顯示目錄數目

root@ubuntu:~# ls -laR |grep "^d" |awk 'END{print "Number of directories."NR}'
Number of directories.17

這些指令集合 ls + grep + awk 的說明如下.

#ls -laR
-l : 列出詳細資料
-a : 顯示所以檔案和目錄,包含 . 開頭的隱藏檔案
-R : recursive 一併顯示子目錄的目錄檔案

grep “^-”
“^” : 指匹配的字符串在行首
“^-” : 找出 – (- 表示為檔案,d 表示為目錄)的字符串在行首

awk ‘END{print “Number of files:”NR}’
awk ‘條件類型1{動作1} 條件類型2{動作2} …’ filename
條件類型是 END (沒有這敘述會把所有處理的結果一一顯示) , 動作 是 print
print 的功能是將欄位資料列出來
單純顯示出 “Number of files:”(只顯示””內的字串,不包含””)
NR (Number of Record) 表示 awk 所處理的資料是到 “第幾行” 了
filename 沒有指定是因為我們用了 | (pipeline) ,所以前面 #ls -laR |grep “^-” 處理完的資料會交由 awk 繼續處理.

範例:搜尋沒有設定密碼的帳號
下面的範例使用了 awk 程式用來找出看誰沒設帳號密碼,awk 程式結構可大約區分三大塊:

[BEGIN { statement }]
[{main}]
[END{ statement }]
root@ubuntu:~# vi nopasswd.awk
BEGIN {
       FS=":"
       total=0
      }

{
    if ( $2 == "" )
   {
       print $1 ": no password"
       total ++
   }
}

END { print "Total no password account=",total}

BEGIN {} 當資料讀取前執行.
FS=”:” (Fields splits) 資料處理自訂欄位的分隔為 “:”.
total=0 定義變數 total
$2 代表第二欄資料
END {} 當資料都讀完處理完畢才會去執行.

root@ubuntu:~# awk -f nopasswd.awk /etc/passwd
Ben: no password
Total no password account= 1

邏輯運算字元

awk 還可以針對 欄位(Field) 的資料做邏輯運算,下面的例子只列印出檔案值大於 4096 的第五欄位內容.

root@ubuntu:~# ll | awk '$5>4096 {print $5}'
23969
13471
5226

可用的 awk 的邏輯運算字元
> (大於)
< (小於)
>= (大於或等於)
<= (小於或等於)
== (等於)
!= (不等於)

發表迴響