一、前言
awk有3個不同版本: awk、nawk和gawk,未作特別說明,一般指gawk。 awk語言最基本的功能是在檔案或字串中基於指定規則來分解抽取訊息,也可以基於指定的規則來輸出資料。完整的awk腳本通常用來格式化文字檔中的資訊。
二、基本語法
awk [opion] 'awk_script' input_file1 [input_file2 ...]
awk的常用選項option有:
① -F fs : 使用作為輸入記錄的字段分隔符,如果省略記錄的字段分隔符此選項,awk使用環境變數IFS的值
② -f filename : 從檔案filename讀取awk_script
③ -v var=value : 為awk_script設定變數
awk有三種運作方式:
,把awk的腳本指令直接放在指令中。 第二種,把awk的所有的腳本命令放在一個腳本檔案中,然後用-f選項來指定要運行的腳本命令檔。 第三種,將awk_script放入腳本檔案並以 #!/bin/awk -f 作為首行,給予該腳本可執行權限,然後在shell下透過鍵入該腳本的腳本名稱呼叫之。 三、awk腳本awk腳本可以由一條或多條awk_cmd組成,對於多個awk_cmd,一個awk_cmd完成後,應該另起一行,以便進行隔。 awk_cmd由兩個部分組成: awk_pattern { actions }。 另外,在awk指令中直接使用awk_script時,awk_script也可以被分成多行書寫,但必須確保整個awk_script被單引號括起來。 awk指令的一般形式:awk ' BEGIN { actions }awk_pattern1 { actions }............awk_patternN actionss; ' inputfile其中BEGIN { actions } 和END { actions } 是可選的。 在awk腳本中可以使用AWK本身內建變量,如下: ARGC 命令列變元個數ARGV 命令行變元數組FILENAME 目前輸入FS 輸入域分隔符,預設為一個空格RS 輸入記錄分隔符NF 目前記錄裡域個數NR 到目前為止記錄數OFS 輸出域分隔符ORS 輸出記錄符號記錄符號awk腳本的運行過程:① 如果BEGIN 區塊存在,awk執行它指定的actions。 ② awk從輸入檔中讀取一行,稱為一筆輸入記錄。 (如果輸入檔省略,將從標準輸入讀取)③ awk將讀入的記錄分割成字段,將第1個字段放入變數$1中,第2個字段放入$2,以此類推。 $0表示整筆記錄。欄位分隔符號使用shell環境變數IFS或由參數指定。 ④ 把目前輸入記錄依序與每一個awk_cmd中awk_pattern比較,看是否匹配,如果相匹配,就執行對應的actions。如果不匹配,就跳過對應的actions,直到比較完所有的awk_cmd。 ⑤ 當一條輸入記錄比較了所有的awk_cmd後,awk讀取輸入的下一行,繼續重複步驟③和④,這個過程一直持續,直到awk讀取到文件尾。 ⑥ 當awk讀完所有的輸入行後,如果存在END,就執行對應的actions。 1)input_file可以是多於一個檔案的檔案列表,awk將依序處理列表中的每個檔案。 2)一條awk_cmd的awk_pattern可以省略,省略時不對輸入記錄進行匹配比較就執行對應的actions。一條awk_cmd的actions 也可以省略,省略時預設的動作為列印目前輸入記錄,即{print $0} 。一條awk_cmd中的awk_pattern和actions不能同時省略。 3) BEGIN區塊和END區塊別位於awk_script的開頭和結尾。 awk_script中只有END區塊或只有BEGIN區塊是被允許的。如果awk_script只有BEGIN { actions } ,awk不會讀取input_file。 4) awk把輸入檔案的資料讀入內存,然後操作內存中的輸入資料副本,awk不會修改輸入檔的內容。 5) awk的總是輸出到標準輸出,如果想讓awk輸出到文件,可以使用重定向。 3.1.awk_patternawk_pattern模式部分決定actions動作部分何時觸發及觸發actions。 awk_pattern可以是以下幾種類型:1) 正規表示式用作awk_pattern: /regexp/注意,正則表達式regexp必須被/包起來awk中正則表達式匹配操作中經常用到匹配操作中經常用到匹配操作的字符: ^ $ . [] | () * // :通用的regexp元字符+ : 匹配其前的單個字符一次以上,是awk自有的元字符,不適用於grep或sed等? : 匹配其前的單個字符1次或0次,是awk自有的元字符,不適用於grep或sed等關於正則表達式的更多內容請參《正則表達式》舉例:awk '/ *$0.[0-9][0-9].*/' input_file比如,行內容為$0.99. helllo的行就可以和上面的正規表示式相匹配2)布林表達式用作awk_pattern,表達式成立時,觸發對應的actions執行。 ① 表達式中可以使用變數(如欄位變數$1,$2等)和/regexp/② 布林表達式中的運算元:關係運算子: = == !=
符合運算子: value ~ /regexp/ 如果value符合/regexp/,則傳回真
value !~ /regexp/ 如果value不符/regexpvalue /,則回傳真
舉例: awk '$2 > 10 {print "ok"}' input_file
awk '$3 ~ /^d/ {print "ok"}' input_file
③ &&() 和|| (或) 可以連接兩個/regexp/或布林表達式,構成混合表達式。 !(非) 可以用於布林表達式或/regexp/之前。
舉例: awk '($1 10) {print $0 "ok"}' input_file
awk '/^d/ || /x$/ {print $0 "ok"}' input_ffile
④ 其它表達式用作awk_script,如賦值表達式等
舉例:
awk '(tot+=$6); END{print "total points :" tot }' input_file // 分號不能省略
tot+=$6 {print $0} END{print "total points :" tot }' input_file // 與上面等效當使用賦值表達式時,表示如果賦值後的變數是數字的話,如果為非0,就匹配,否則不匹配;如果為字串的話,非空就為匹配,否則不匹配。# print a header firstBEGIN{print "Student Date Member No. Grade Age anced Max" ====== ===============================================" }# let's add the scores of points gained(tot+=$6);# finished processing now let's print the total and average point 🜆
🜎 " tot
print "Average Club Student points :" tot/N
}
2.9. awk數組:k 'BEGIN {record="123#456#789";split(record,myarray,"#")}
END { for (i in myarray) {print myarray[i]} }
3.0 10kk一.條件判斷語句(if)
if(表達式) #if ( Variable in Array )
語句1
else
語句2個語句
中"如果你為了方便Unix awk判斷也方便你自已閱讀,你最好將多個語句用{}括起來。 Unix awk分枝結構允許嵌套,其格式為:
if(表達式)
{語句1}
elsechen if(表達式)
句語句
@localhost nginx]# awk 'BEGIN{ test=100;if(test>90){ print "非常 good"} print "good";
}
else
{
print "no pass";
}
}'
每條指令語句後面可以用「;」號結尾。
二.循環語句(while,for,do)
1.while語句
while(表達式)
例子:
[chengmo@localhost nginx]# awk 'BEGIN{
test=100;
total=0;
total+=i;
i++;
}
5050%
格式1:
for(變數in 陣列)
{語句}for(k in ENVIRON) { print k"="ENVIRON[k];}}' SS =/ usr/libexec/openssh/gnome-ssh-askpass
SELINUX_LEVEL_REQUESTED=
SELINUX_ROLE_REQUESTED=
LANG=zh_CN.GB2312
chen
mo@localhost nginx]# awk 'BEGIN{ total=0;for(i=0;i{ total+=i;}
print total;
}'
50503.do循環格式:
do
i=0;
do
{
break 當 break 語句用於 while 或 for 語句時,導致退出程式循環。
continue 當 continue 語句用於 while 或 for 語句時,將程式循環移到下一個迭代。
next 能導致讀入下一個輸入行,並回到腳本的頂部。這可以避免對目前輸入行執行其他的操作過程。
exit 語句使主輸入循環退出並將控制權轉移到END,如果END存在的話。如果沒有定義END規則,或在END中套用exit語句,則終止腳本的執行。
NR與FNR:
QUOTE:
A. awk對多重輸入檔案的執行順序是,先將程式碼作用於第一個檔案(一行行讀入),然後該重複的程式碼再作用於第二個文件,再作用於第三個檔案。
FNR:目前檔案本身的行數(不考慮前幾個輸入檔案的自身行數及總數)
例如:data1.txt中有40行,data2.txt中有50行,那麼awk '{}' data1.txt data2.
42…90
QUOTE:
A. getline從整體來說,應這麼理解它的用法:
當其左右無重定向符 | 或
var 或$0(無變數);應該注意到,由於awk在處理getline之前已經讀入了一行,所以getline得到
的返回結果是隔行的。
當其左右有重定向符| 或
get line
get 文件的第一行,而不是隔行。
B. getline用法大致可分為三大類(每大類又分兩小類),即總共有6種用法。程式碼如下:
QUOTE:
nawk 'BEGIN{“cat data.txt”|getline d; print d}' data2.txt
nawk 'BEGIN{“cat data.txt”|getline; print $0}' data2 .txt
nawk 'BEGIN{getline d
nawk 'BEGIN{getline
.程式碼皆實作「只列印data.txt檔案的第一行」(若列印全部行,用循環)
eg. nawk 'BEGIN{FS=”:”;while(getline0 ){print $1}}' data.txt
QUOTE:
nawk '{getline d; print d”#”$3}' data.txt
awkk ,然後把下一行指定給變數d,再先列印d,由於d後面有換行符,所以後面緊跟的#會覆蓋d,後面的$3同樣也會覆蓋d。
QUOTE:
nawk '{getline; print $0”#”$3}' data.txt
awk先讀入第一行接著處理getline函數,然後把下一行指定給$0,現在的$0已經是下一行內容,後面的#和$3(從$0取)會覆蓋$0的內容。
在awk中,有時需要呼叫系統工具來完成awk不擅長的工作,awk提供的system指令可以用來執行,但收不到外部工具的輸出結果。還好可以運用getline來滿足這個需求。例如
test.awk:
{
datecommand="/bin/date -j -f "%d/%b/%Y:%H:%M:%S" " $olddatestr ""+%Y %m%d %H%M%S"";
datecommand | getline newdatestr
close(datecommand);
}
有上限,而且不大(比如說16),所以最後做一個close是好習慣。把指令串定義為變數也是為了close的時候方便