導讀
相對于 sed 常常作用于一整行的處理辫诅,awk 則比較傾向于將一行分成數(shù)個“字段”來處理凭戴。
本文翻譯自 simple awk tutorial
習慣了英文者,可自行前往閱讀炕矮。
接下來的例子中會使用到 employee.txt 文件么夫。
$ cat employee.txt 100 Thomas Manager Sales $5,000 200 Jason Developer Technology $5,500 300 Raj Sysadmin Technology $7,000 400 Nisha Manager Marketing $9,500 500 Randy Manager Sales $6,000
awk是做什么的?
最簡單的 awk 用法是基于列的數(shù)據(jù)處理肤视,比如說表格档痪,使用標準輸入將數(shù)據(jù)導入。變量 $1, $2...表示當前輸入行的第一列邢滑,第二列...腐螟。打印出一個文件的第二列,你可能會使用下面的 awk 腳本:
awk < file '{ print $2 }'
這意味著“每一行困后,打印出第二個字段”
例如:
$awk < employee.txt '{ print $2 }' Thomas Jason Raj Nisha Randy
為了打印出第二列和第三列乐纸,可以
awk < file '{ print $2, $3 }'
分隔符
awk 將行分隔為字段,默認會使用空白符(whitespace)來分隔摇予,也就是空格符(spaces)或制表符(tabs)汽绢。 你可以使用 -F 選項來指定其它字符為分隔符。例如侧戴,為了打印出當前系統(tǒng)中所有用戶的主目錄宁昭,你可以
$awk < /etc/passwd -F: '{ print $6 }'
passwd 的文件內(nèi)容以冒號來分隔,主目錄在第六個字段酗宋。
運算
awk是一種弱類型語言积仗;變量既可以是字符串,也可以是數(shù)字本缠,這取決于你怎樣引用它們斥扛。所有的數(shù)字都是浮點型的。所以丹锹,為了實現(xiàn)華氏溫度與攝氏溫度之間的轉(zhuǎn)換稀颁,你可以
awk '{ print ($1-32)*(5/9) }'
標準輸入的華氏溫度會被轉(zhuǎn)換為攝氏溫度,直到遇到 EOF楣黍,該 awk 程序停止匾灶。
可選的操作符與C基本一樣。緊接著的兩個字符串表達式(以空格分隔或沒有空格)租漂,會連接阶女〖彰樱‘+’ 總是加法。
echo 5 4 | awk '{ print $1 + $2 }
會輸出 “9”秃踩,然而
echo 5 4 | awk '{ print $1 $2 }'
會輸出 “54”衬鱼,注意
echo 5 4 | awk '{ print $1, $2 }'
會輸出 “5 4”。
變量
awk 有一些內(nèi)置的憔杨、自動置值的變量鸟赫,比如上文提到的$1。其它的內(nèi)置變量中消别,適合初學者的抛蚤,也就是 $0 和 NF 了,前者表示當前輸入行寻狂,后者表示當前輸入行($0)的字段總數(shù)岁经。$NF表示當前輸入行的最后一個字段。
你可以定義自己的變量蛇券,除了 awk 保留的關(guān)鍵詞缀壤,你可以用任何名字來引用它。變量沒有明確賦值的怀读,字符串為“”诉位,數(shù)字為0。
例如菜枷,下面的代碼會打印出每行數(shù)字的平均值:
awk '{ tot=0; for (i=1; i <= NF; i++) tot += $i; print tot/NF; }'
使用 $i 去取第 i 個變量的值, for 循環(huán)與C語言類似叁丧。 tot 在代碼的開頭作初始化的原因啤誊,是這個代碼運行于每一個輸入行,如若不拥娄,當開始運行第二行的時候蚊锹, tot 將具有第一行結(jié)束時的值。
塊Block
可能稚瘾,你僅有一些特殊字段的數(shù)字需要單獨相加牡昆。為了這樣做,你需要在結(jié)束時打印結(jié)果摊欠。采用的方法為
awk '{ tot += $1; n += 1; } END { print tot/n }'
注意兩個語句塊的使用丢烘。第二個之前有個 END;意味著一旦所有的輸入處理結(jié)果些椒,就運行這個語句塊播瞳。一般,你可以在語句塊之前添加各種條件免糕,僅當條件滿足時語句塊才被執(zhí)行赢乓。也就是忧侧,你可以
awk '$1 == 0 { print $2 }'
僅在第一個字段為0時才打印第二個字段。你還可以使用正則表達式來匹配行數(shù)據(jù):
awk '/^test/' { print $2 }
如果你沒有添加條件牌芋,每行數(shù)據(jù)輸入時都會運行塊語句蚓炬。
語句塊的特殊條件 BEGIN 和 END,分別運行于輸入數(shù)據(jù)的處理之前和處理之后躺屁。
printf
awk 包含了 printf 語句试吁,本質(zhì)上類似于C語言的 printf。當你想要格式化輸出楼咳,或者將多種元素整合到一行熄捍,可以使用它。(print 暗含增加一個'\n'母怜;printf不會)余耽。
比如,移除每一行第一字段
awk '{ for (i=2; i<=NF; i++) printf "%s ", $i; printf "\n"; }'
注意苹熏,使用NF迭代所有的字段碟贾,顯示地使用 printf 輸出 '\n'。