透過 sed 與 awk 都可以把文件做過濾和轉換成新的輸出內容.不過 sed – https://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 的邏輯運算字元
> (大於)
< (小於)
>= (大於或等於)
<= (小於或等於)
== (等於)
!= (不等於)
您好:請問如何將以下透過迴圈完成?就是我想將每一行中的所有欄位都一一讀出來出來處理, 如何將{print $1} ~{print $4} 用變數取代, 試了很久, 都不成功
echo $error_num_colume | awk -F’/’ ‘{print $1}’ >> $driver_path/final_observation.txt
echo $error_num_colume | awk -F’/’ ‘{print $2}’ >> $driver_path/final_observation.txt
echo $error_num_colume | awk -F’/’ ‘{print $3}’ >> $driver_path/final_observation.txt
echo $error_num_colume | awk -F’/’ ‘{print $4}’ >> $driver_path/final_observation.txt