透過 sed 與 awk 都可以把文件做過濾和轉換成新的輸出內容.不過 sed – https://benjr.tw/97129 適合用於一整行的資料處理,而 awk 則比較適合將一整行做多個 欄位(Field) 的資料處理.先來看看 awk 的幾個範例.
# mawk [-W option] [-F value] [-v var=value] [--] 'program text' [file...]
awk 是 mawk 的連結,兩種方式都可以下指令.
前面 https://benjr.tw/97139 有提到 OFS , ORS 他們是內建的變數,他們所代表的意思如下:
- OFS 代表的意思 inserted between fields on output, 等同 = ” “.
- ORS 代表的意思 terminates each record on output, 等同 = “\n” (newline)
還有其他相關變數名稱下面繼續說明.
OFMT
代表的意思 format for printing numbers; 主要是將數字輸出時的格式,預設格式為 “%.6g” 代表整數與小數點只保留 6個數字,OFMT 可以自訂.
下面範例就是將 pi 數字輸出時的格式設定.
root@ubuntu:~# cat OFMT.awk BEGIN { pi=3.14159265359; print "Default OFMT:", pi; OFMT="%.4g"; print "%.4g OFMT:", pi; print "---using f---"; OFMT="%.0f"; print "%.0f OFMT:", pi; OFMT="%.3f"; print "%.3f OFMT:", pi; }
ANSI C format
- %c char single character
- %d (%i) int signed integer
- %e (%E) float or double exponential format
- %f float or double signed decimal
- %g (%G) float or double use %f or %e as required
- %o int unsigned octal value
- %p pointer address stored in pointer
- %s array of char sequence of characters
- %u int unsigned decimal
- %x (%X) int unsigned hex value
root@ubuntu:~# awk -f OFMT.awk Default OFMT: 3.14159 %.4g OFMT: 3.142 ---using f--- %.0f OFMT: 3 %.3f OFMT: 3.142
FILENAME – 目前處理資料的檔案名稱.
FNR – (File Number of Field) 目前處理資料檔案的第幾行 .
下面範例會輸出 檔案名稱 (FILENAME) 以及 FNR 目前處理資料檔案的第幾行
root@ubuntu:~# awk 'END{print "Filename:" FILENAME , "\tCurrent Line:" FNR }' /etc/passwd Filename:/etc/passwd Current Line:41
沒有 END 時,Print 會列印出每一行處理的資料,使用 END 時只會在資料讀取處理完畢後,執行一次.(關於 awk 的程式結構 請參考 https://benjr.tw/97423).
NR – (Number of Record) 目前處理的資料的第幾行.
下面範例排除特定列 (第2~5列) ,! 等同 not
root@ubuntu:~# ls -l | nl | awk '!(NR>=2 && NR<=5){print $0}' 1 total 28 6 -rw-r--r-- 1 root root 5 Jul 10 00:23 text1.txt 7 -rw-r--r-- 1 root root 5 Jul 10 00:26 text2.txt 8 -rwxr-xr-x 1 root root 106 Jul 10 01:20 while.sh
NF – (Number of Field) 目前行資料中有幾個 欄位(Field) 的資料.
下面範例使用 ll 來當資料,ll 輸出的第一行的資料是 total # ,所以只有兩個欄位(Field) 的資料.
root@ubuntu:~# ll | awk '{print "Line:"NR "\tColumn:"NF}' Line:1 Column:2 Line:2 Column:9 Line:3 Column:9 Line:4 Column:9 Line:5 Column:9 Line:6 Column:9 Line:7 Column:9 Line:8 Column:9 Line:9 Column:9 Line:10 Column:9 Line:11 Column:9 Line:12 Column:9
FS – (Fields splits) 預設的欄位區分是以 空白或是 tab 做分隔,要改成其他如 冒號 “:” 來作欄位的分隔時就需要設定 FS 變數.
下面範例處理 /etc/passwd ,並定義了 FS (Fields splits) 為 “:” , \t (tab) , $1 代表第一欄資料
root@ubuntu:~# awk '{FS=":"} {print "User:\t"$1}' /etc/passwd User: root:x:0:0:root:/root:/bin/bash User: daemon User: bin User: sys User: sync User: games User: man User: lp User: mail User: news User: uucp
第一行沒有處理到, awk 在執行時就會先把第一行的資料讀取進來等待處理,所以 FS 的定義必須透過 BEGIN{} ,所定義的內容只會執行一次. (關於 awk 的程式結構 請參考 https://benjr.tw/97423 ). .
root@ubuntu:~# awk 'BEGIN{FS=":"} {print "User:\t"$1}' /etc/passwd User: root User: daemon User: bin User: sys User: sync User: games User: man User: lp User: mail User: news User: uucp
其他可用變數名稱
ARGC – number of command line arguments.
ARGV – array of command line arguments, 0..ARGC-1.
CONVFMT – format for internal conversion of numbers to string.
ENVIRON – array indexed by environment variables. An environment string, var=value is stored as ENVIRON[var] = value.
RLENGTH – length set by the last call to the built-in function,match().
RS – input record separator,.
RSTART – index set by the last call to match().
SUBSEP – used to build multiple array subscripts.