新聞中心
awk '條件類(lèi)型1{動(dòng)作1} 條件類(lèi)型2{動(dòng)作2} ...' filename
功能
相較于
sed
常常作用于一整個(gè)行的處理,
awk
則比較傾向于一行當(dāng)中分成數(shù)個(gè)『字段』來(lái)處理。
描述
awk 的處理流程
讀入第一行,并將第一行的資料填入 $0, $1, $2…. 等變數(shù)當(dāng)中;
依據(jù) “條件類(lèi)型” 的限制,判斷是否需要進(jìn)行后面的 “動(dòng)作”;
做完所有的動(dòng)作與條件類(lèi)型;
若還有后續(xù)的『行』的數(shù)據(jù),則重復(fù)上面 1~3 的步驟,直到所有的數(shù)據(jù)都讀完為止。
經(jīng)過(guò)這樣的步驟,您會(huì)曉得, awk 是『以行為一次處理的單位』, 而『以字段為最小的處理單位』。
常用變量(變量名稱 代表意義)
NF
每一行 (
$0
) 擁有的字段總數(shù)
NR
目前 awk 所處理的是『第幾行』數(shù)據(jù)
FS
目前的分隔字符,預(yù)設(shè)是空格鍵
每一行的每個(gè)字段的變量名稱就是
$1
,
$2
… 等。還有個(gè)例外,那就是
$0
代表一整行的意思。
注意,
awk
后續(xù)的所有動(dòng)作以 ‘ 括住, 所以,內(nèi)容如果想要以
print
打印時(shí),記得,非變量的文字部分,
printf
提到的格式中,都需要使用雙引號(hào).
邏輯運(yùn)算符號(hào)
大于
< 小于
= 大于或等于
<= 小于或等于
== 等于
!= 不等于
舉例
假設(shè)輸入輸出如下:
$last
dmtsai pts/0 192.168.1.12 Mon Aug 22 09:40 still logged in
root tty1 Mon Aug 15 11:38 - 11:39 (00:01)
reboot system boot 2.6.11 Sun Aug 14 18:18 (7+15:41)
dmtsai pts/0 192.168.1.12 Fri Aug 12 12:07 - 12:08 (00:01)
打印每行的第1列和第三列,并且用[TAB]隔開(kāi)
輸入輸出如下
$last | awk '{print $1 "\t" $3}' dmtsai 192.168.1.12 root Mon reboot boot dmtsai 192.168.1.12
這里,我們沒(méi)有設(shè)定條件,也就是無(wú)論哪一行都做同樣處理,所以第2,3行顯示的有點(diǎn)”不正常”。由此可知awk是“迭代”處理每一行的。
列出每一行的賬號(hào),目前處理的行數(shù), 以及該行有多少字段
輸入輸出如下
$last | awk '{print $1 "\t lines: " NR "\t columes: " NF}' dmtsai lines: 1 columes: 10 root lines: 2 columes: 9 reboot lines: 3 columes: 9 dmtsai lines: 4 columes: 10
查閱
/etc/passwd
,第3欄小于 10 以下的數(shù)據(jù),并且僅列出賬號(hào)與第3欄輸入輸出如下:
$cat /etc/passwd | awk '{FS=":"} $3 < 10 {print $1 "\t " $3}' root:x:0:0:root:/root:/bin/bash bin 1 daemon 2 ......(以下省略)......
這里,在
/etc/passwd
當(dāng)中是以冒號(hào) “:” 來(lái)作為字段的分隔,所以需要設(shè)置一下。但是我們讀入第一行的時(shí)候, 那些變數(shù) $1, $2… 預(yù)設(shè)還以空格鍵為分隔,所以雖然我們定義了 FS=”:” 了, 但是卻僅能在第二行后才開(kāi)始生效(可能因?yàn)橐话愕谝恍袃H僅是列名不需處理,而這里卻是特例,見(jiàn)例4改進(jìn))。對(duì)上面過(guò)濾的操作改進(jìn)
輸入輸出如下:
$ cat /etc/passwd | awk 'BEGIN {FS=":"} $3 < 10 {print $1 "\t " $3}' root 0 bin 1 daemon 2 ......(以下省略)......
利用 BEGIN 這個(gè)關(guān)鍵詞,可以從第一行就生效了。實(shí)際除了BEGIN,還有END。
假設(shè)如下表(pay.txt)
Name 1st 2nd 3th
VBird 23000 24000 25000
DMTsai 21000 20000 23000
Bird2 43000 42000 41000
計(jì)算每一行總額,添加追加到最后一列
輸入輸出如下:
$awk 'NR==1{printf "%10s %10s %10s %10s %10s\n",$1,$2,$3,$4,"Total" } NR>=2{total = $2 + $3 + $4 printf "%10s %10d %10d %10d %10.2f\n", $1, $2, $3, $4, total}' Name 1st 2nd 3th Total VBird 23000 24000 25000 72000.00 DMTsai 21000 20000 23000 64000.00 Bird2 43000 42000 41000 126000.00
注意:所有的動(dòng)作在
{}
內(nèi),如需多個(gè)指令輔助,可利用分號(hào);
間隔或直接以[Enter]
按鍵來(lái)隔開(kāi)每個(gè)指令,例如上面的 NR>=2 后面接的動(dòng)作, 利用 total = … 那個(gè)指令來(lái)指定加總,而后續(xù)則以printf
來(lái)格式化輸;格式化輸出時(shí),在printf
的格式設(shè)定當(dāng)中,務(wù)必加上\n
,才能進(jìn)行分行;與bash shell
的變量不同,在awk
當(dāng)中,變量可以直接使用,不需加上$
符號(hào)(如total)。
其它
參考資料: 《鳥(niǎo)哥的私房菜》
網(wǎng)站題目:Linux命令學(xué)習(xí)手冊(cè)-awk-創(chuàng)新互聯(lián)
網(wǎng)站鏈接:http://www.ef60e0e.cn/article/ggepj.html