awk 的指令行啟動方式有兩種:
awk [options] 'script' var=value file(s)
awk [options] -f scriptfile var=value file(s)
可在指令行直接使用 script,或是將 script 放入檔案中以 scriptfile 形式執行。變數可以在指令行中指定其值。值可以是字元字串或是 shell 變數($name)或是指令替代('cmd'),但所指定的變數值只有在讀入一行輸入以後才生效(也就是在 BEGIN 之後)。awk 可以一次處理多個檔案。若不指定檔案,或是用 - 來代替檔名,則從標準輸入取得輸入的資料。
可用的 options 如下:
-Fc 將欄分隔字元設定為 c。這和系統變數 FS 的設定作用相同。Nawk 中的 c 可以是一個常規表示式 (regular expression)。每行輸入(或是記錄的輸入)都由分隔符號(預設為空白字元)隔成一個一個欄位。你可以透過 $1, $2,..., $n 等變數來存取各個欄位的值。$0 則代表整筆記錄(或是這一整行)。
-v var=value 將 value 的值指定給變數 var。這可以在 script 開始執行前就指定一個變數的值(僅 nawk 可使用)。
例如,如果要將前三欄分別印在不同的行中,指令如下:
awk -F: '{print $1; print $2; print $3}' /etc/passwd
詳見本章之後的 "pattern 和程序 " 一節
awk 概說
awk 主要是以樣式比對來處理檔案,尤其是用於資料庫中。後來推出 nawk,加入了不少新功能,而目前 SVR4 的系統上都已加上 nawk 了,不過 awk 還是可以使用(實際上是一個連到oawk 的連結)。下一版的 System V 中,nawk 將會取代 awk。(還有一個由 GNU 出的 gawk,也包括了所有 nawk 的功能。)
awk 原有功能如下:
. 純文字檔案可視為一個很大的文字資料庫,每個字都是一個欄位。
. 利用變數來更動資料庫
. 進行數學或是字串運算
. 可使用迴圈或是條件式來控制流程
. 輸出可以格式化
nawk 的新功能如下:
. 定義新的函式
. 從 script 中執行 UNIX 指令
. 處理 UNIX 指令的輸出
. 指令行參數處理較容易
. 多重輸入
pattern 和程序
awk script 由 pattern 和程序(procedure)組成
pattern {procedure}
若不加上 pattern,則 [procedure] 對所有的行作用。若不加上 [procedure],則列出符合 pattern 的行。
-----------------------------------------------------------------------------
Pattern
pattern 可以是下列任一種型態:
/regular expression/
relational expression
pattern-matching expression
BEGIN
END
. expression 可以是引用字串或是數字、運算子、函式、變數或是任何定義過的系統變數。
. regular expression 所使用的中介字元在第六章有詳細說明。
. ^、$ 兩個符號分別代表一個欄位的開頭和結尾,而非一行的開頭和結尾。
. 比較式所使用的運算子在後面 " 運算子 " 一節有更詳細的說明。可以拿數字或是自串來做比較。如 $2>$1 會印出第二欄大於第一欄的行。
. pattern matching 使用 ~ 和 !~ 來表示符合和不符合。詳見 " 運算子 " 一節
. BEGIN 可以指定讀入資料之前所執行的程序。(通常在此定義全域變數)
. END 可指定在讀入最後一行資料以後所執行的程序。
除了 BEGIN 和 END 以外。pattern 都可以用 ||(or)、&&(and)、!(not)連起來。若要一次指定一整個範圍,也可以用
pattern, pattern
的形式。
-----------------------------------------------------------------------------
程序(Procedure)
程序的結構,最外層是 {},中間可以有指令,函式或是指定變數,彼此以換行字元或是分號分開。指令分為下面四類:
. 指定變數或是陣列
. 列印指令
. 內建指令
. 流程控制
-----------------------------------------------------------------------------
簡單的例子
1. 印出每一行的第一欄:
{ print $1 }
2. 印出所有有 pattern 的行:
/pattern/
3. 將所有含有 pattern 的行的第一欄印出:
/pattern/{ print $1 }
4. 選擇超過兩欄的行:
NF > 2
5. 將輸入的資料當做一些行的集合:
BEGIN { FS = "\n"; RS = "" }
6. 將第一欄為 URGENT 的行取出後,將其第二第三欄以相反順序印出:
$1 ~ /URGENT/ { print $3, $2 }
7. 印出找到 pattern 的次數:
/pattern/ { ++x }
END { print x }
8. 將第二欄的數字加總後印出:
{total += $2 };
END { print "column total is", total}
9. 印出少於 20 個字元的行:
length < 20
10. 印出以 Name 開頭,而且內容恰有七欄的行:
NF == 7 && /^Name:/
11. 將所有欄的順序顛倒:
{ for (i = NF; i >= 1; i--) print $I }
Awk 系統變數
<<<<<< 排版請注意 ,左兩欄不翻 >>>>>>>>>>>>>
版本 變數 說明
awk 目前檔名
欄位分隔字元(預設為空白字元)
目前行中的欄位數
目前的行數
輸出的欄位分隔字元
輸出的行分隔字元
行分隔字元
整個輸入的資料
資料中的第 n 欄,欄位以 FS 分開
nawk 指令行的參數個數
儲存指令行參數的陣列
和 NR 類似,但指目前檔案
數字輸出格式
match 指令執行後所找到的字串起點
match 指令所找到的字串長度
陣列足碼的分隔字元(預設為 \034)
gawk 環境變數陣列
不管大小寫
----------------------------------------------------------------
運算子
下列為 awk 中所使用的運算子,以優先順序排列:
符號 意義
= += -= *= /= %= ^= 指定值
?: C 的條件式(gawk 與 nawk)
|| 邏輯 OR
&& 邏輯 AND
~ !~ 符合或不符合該 常規表示式
< <= > >= != == 關係運算子
(blank) 串接
+ - 加減
* / % 乘除和取餘數
+ - ! 正號負號與 NOT
^ 指數
++ -- 加 1 或減 1,可用後置或前置式
$ 欄位符號
----------------------------------------------------------------
變數和陣列
若要指定變數的值,可用下面的形式:
var = value
比如 FS = ","。所指定的值可以包含 +、-、*、/ 和 %。
要定義陣列則需使用 split 函式,或是在指定變數值時建立。++、+=、-= 的用法和 C 語言一樣,可以用來取用陣列。陣列元素可以用足碼取用,如 array[1], ..., array[n],或是使用其名稱。比如,若要紀錄某個 pattern 出現的次數,可用下面的指令:
<<<< code >>>>>>>
指令分類列表
awk 指令可分為下列幾類
<<<<<< 排版請注意 ,中間的指令不用翻 >>>>>
數學運算 字串功能 流程控制 輸出入 其它
<<<<<< 下面還有兩小行字 >>>>>
* 用於 nawk
+ 用於 gawk
p11-7
指令解說
指令解說中有 N 者,為 nawk 專用指令,有 G 者為 gawk 專用指令,若無指定,則各版本的 awk 皆可使用。
--------------------------------------
atan2(y,x)
傳回 y/x 的 arc-tangent 值,單位為弧度。{N}
--------------------------------------
break
從 while 或是 for 迴圈跳出。
--------------------------------------
close(filename-expr)
close(command-expr)
大部份的 awk 一次只能開十個檔案外加一個 pipe。所以 nawk 提供了 close 指令來關閉一些檔案(或是 pipe)。其中 expr 為開啟該檔案或是 pipe 的運算式。{N}
--------------------------------------
continue
直接繼續下一次 while 或 for 的迴圈。
--------------------------------------
cos(x)
傳回 x 的 cosine 值,單位為弧度。
--------------------------------------
delete(array[element])
將陣列 array 中的 element 元素刪除。{N}
--------------------------------------
do
body
while(expr)
先執行 body 中的指令,然後檢查 expr,若 expr 成立,則回到 do 然後再執行 body,如此周而復始。{N}
--------------------------------------
exit
不繼續執行下去,直接去執行 END 的程序然後跳出。
--------------------------------------
exp(arg)
傳回 e 的 arg 次方(log的反函數)。
--------------------------------------
for(i=lower; i<=upper; i++)
command
當 i 之值介於 lower 和 upper 之間時,執行 command,然後將 i 加 1。若一次執行多個指令則需加上 {}。<= 可用任何關係運算子取代。而 i 可以用 ++ 或 -- 來遞增或遞減。
--------------------------------------
function name(parameter-list){
statements
}
將 name 定義為使用者的函式,傳入參數 parameter-list,然後執行 awk 指令 statements。
--------------------------------------
getline [var][
或
command | getline [var]
讀取下一行輸入。原本的 awk 並不能一次開很多個輸入流。第一種形式從檔案中讀入資料,而第二種則將 command 的輸出當做輸入。兩種形式一次都只讀入一行,若再執行一次,則再讀入一行。讀入的資料指定為 $0,然後分解為欄位,設定 NF、NR 和 FNR。若指定 var,則結果會指定給 var,而原來的 $0 保持不變。所以若將結果指定給變數,則目前行內容不變。若讀入成功則傳回 0,若讀到 end-of-line 則傳回 1,而因其它原因失敗時傳回 -1。{N}
--------------------------------------
gsub(r,s,t)
將 t 字串中每個符合 r 這個常規表示式的部份,以 s 來取代。傳回值為取代之次數。若不指定 t,預設為 $0。{N}
--------------------------------------
if (condition)
command
[else]
[command]
若 condition 條件成立,則執行 command 指令。若不成立,則執行下面的 else 後的指令。condition 可以是關係條件式或是 pattern(如 "if ($1 ~ /{Aa].*/)" )。若一次要執行多個指令則需加上 {}。
--------------------------------------
index(str,substr)
傳回 substr 在 str 內所在的位置。
--------------------------------------
int(arg)
傳回 arg 的整數值。
--------------------------------------
length(arg)
傳回 arg 的長度。若不指定 arg,預設為 $0。如此一來,length 就可以當做目前行的長度的變數使用。
--------------------------------------
log(arg)
exp 的反函數,log 傳回的是 arg 的對數值。
--------------------------------------
match(s,r)
在字串 s 中尋找符合 r 這個 常規表示式 的字串。若找到,則傳回符合字串的開頭位置,若沒找到則傳回 0。見 RSTART 和 RLENGTH。{N}
--------------------------------------
next
讀入下一行然後重新執行 pattern或程序的敘述。
--------------------------------------
print [args] [destination]
將 args 印出。通常 args 是欄位,但也可以是變數。若要印出字串,則需加上引用符號。欄位的印出順序和其原來的排列順序相同。若在參數中使用 "," 當分隔字元,則輸出時欄位會以 OFS 來當做分隔字元。若用空白當分隔字元,則輸出時會將這些欄位合併。destination 可以是檔案或是 pipe (如 >file)。
--------------------------------------
printf [format[, expression(s)]]
格式化輸出。輸出格式由 format 參數決定。輸出的參數個數必須符合 format 所需的個數。
format 的使用法和 C 語言中的 printf 一樣。下列為常見的格式:
%s 字串。
%d 十進位數字。
%n.mf 浮點數,n 為總共的位數,m 為小數點後的位數。
%[-]nc 為 c 這種格式指定最小欄位寬度。加上 - 則向左對齊,不加則向右對齊。
format 也可以含有 escape 字元。常用的有 \n(換行字元) 和 \t(tab)
若加上引用符號,則可以在 args 中加入字串或是空白字元。若要印出多個變數或是欄位,則必須用多個格式 format。
範例:
使用下列 script:
{printf ("The sum on line %s is %d \n", NR, $1+$2)}
下面是輸入:
5 5
輸出如下,加上換行
The sum on line 1 is 10.
--------------------------------------
rand()
產生介於 0 和 1 的亂數。這個函式在同一個 script 中執行時會傳回同一個值,若要改變其值,則需用 srand()來改變其 seed 的值。{N}
--------------------------------------
return [expr]
在函式結束前將 expr 做為傳回值傳回去。{N}
--------------------------------------
sin(x)
傳回 x 的 sine 值,單位為弧度。
--------------------------------------
split(string,array[,sep])
將 string 字串分解成 array[1], ..., array[n]。在字串中每遇到一次 sep 分隔符號就分解一次。若不指定 sep,則使用預設的 FS。最後傳回所建立的陣列大小。
--------------------------------------
sprintf [format[,expression(s)]]
將 expression 以 format 格式化後當做傳回值傳回。資料格式化後並不印出。{N}
--------------------------------------
sqrt(arg)
傳回 arg 開根號之值。
--------------------------------------
srand(expr)
用 expr 來產生一個新的亂數 seed。預設為目前時間。{N}
--------------------------------------
sub(r,s,t)
將 t 字串中第一個符合 r 這個常規表示式的部份,以 s 來取代。若成功則傳回 0,反之則傳回 1。若不指定 t,預設為 $0。{N}
--------------------------------------
substr(string,m,[n])
將 string 字串中從 m 開始的 n 個字元當作字串傳回。若無 n,則從第 m 個字元到字串尾。
--------------------------------------
system(command)
執行指定的 command,然後傳回其狀態。通常狀態為 1(成功)、0(結束)或是 -1(失敗) 這個指令的輸出無法從 script 中取得。若須要指令的輸出,請見 getline。{N}
--------------------------------------
tolower(str)
將 str 中所有大寫的字元都改為小寫後傳回字串 {G}。
--------------------------------------
toupper(str)
將 str 中所有小寫的字元都改為大寫後傳回字串 {G}。
--------------------------------------
while (condition)
command
當 condition 成立時執行 command(有關 condition 組成請見 if)。若要一次執行多個指令需加上 {}。
沒有留言:
張貼留言