跳轉到內容

Unix 指南/解釋/awk

來自華夏公益教科書,開放的書籍,為開放的世界

名稱 'awk' 來自三位最初開發它的人的名字 - Aho、Weinberger 和 Kernighan。它是一種程式語言,使用模式-動作表示式將輸入轉換為輸出。它處理輸入(通常是資料檔案),在每行中搜索給定的模式。任何與給定模式匹配的行都會應用動作,並且這構成了輸出。不匹配的行將被忽略。

每個輸入行都由分隔符字元(預設是空格)劃分為欄位,並且模式可以與這些欄位匹配,因為它們以通常的 Unix 樣式引用 - $1 是欄位 1,$2 是欄位 2 等。$0 表示整個輸入行。

如果沒有指定模式,則選擇所有輸入行。如果沒有指定動作,則預設動作是列印整行。因此,如果您只想列印輸入的子集,您只需要提供一個將產生所需結果的模式,Awk 將按原樣列印輸入。

但是,您也可以以相同的方式指定要輸出的欄位,例如 print $1。

一個簡單的例子

awk '$1 ~ /A/ { print $2 " " $3 }' /etc/passwd

程式結構

[編輯 | 編輯原始碼]

awk 程式由一個或多個模式-動作語句組成

pattern   { action }
pattern   { action }
 :
 :

awk 掃描資料輸入行,並對與任何指定模式匹配的這些行執行操作。


執行 AWK

[編輯 | 編輯原始碼]

在這裡,我們從一個 shell 指令碼 awk1.sh 中呼叫 awk

#!/bin/bash

# awk1.sh
awk '
       { print }
' $1

沒有模式,因此饋送到 awk 的每一行都匹配,並且會呼叫動作。這會導致檔案的每一行都列印到螢幕上。因此,awk1.sh 的行為類似於 cat

為了演示,建立檔案 numeric.dat,其內容為

1 one   i
2 two   ii
3 three iii
4 four  iv
5 five  v
6 six   vi
7 seven vii
8 eight viii
9 nine  ix
10 ten  x

numeric.dat 上執行 awk1.sh(不要忘記使指令碼可執行)

./awk1.sh numeric.dat
1 one   i
2 two   ii
3 three iii
4 four  iv
5 five  v
6 six   vi
7 seven vii
8 eight viii
9 nine  ix
10 ten  x

(注意如何使用    ./    執行指令碼。)

表示式 =

[編輯 | 編輯原始碼]

如果第一個欄位等於 1,則列印整行

#!/bin/sh
# awk1.sh
awk '
    $1 == 1 { print $0 }
' $1

結果為

1 one i

如果第二個欄位等於 "two",則列印整行

$2 == "two" { print $0 }

結果為

2 two ii

如果第一個欄位大於 5,則列印第三個欄位

$1 > 5 { print $3 }

結果為

 vi
 vii
 viii
 ix
 x

正則表示式

[編輯 | 編輯原始碼]

如果模式 "ix" 在任何欄位中匹配,則列印輸入行

/ix/ { print $0 } 

結果為

6 six   vi
9 nine  ix

如果模式 "ix" 在第三個欄位中匹配,則列印輸入行

$3 ~ /ix/ { print $0 } 

結果為

9 nine  ix

列印不包含模式 "x" 的輸入行

$0 !~ /x/ { print }

結果為

1 one   i
2 two   ii
3 three iii
4 four  iv
5 five  v
7 seven vii
8 eight viii

複合表示式

[編輯 | 編輯原始碼]

列印第三個欄位與模式 "x" 匹配或第一個欄位小於或等於 3 的行。

$3 ~ /x/ ||  $1 <= 3  { print $0 }

結果為

1 one   i
2 two   ii
3 three iii
9 nine  ix
10 ten  x

列印第三個欄位與模式 "vi" 匹配且第二個欄位以字母 "s" 開頭的行。

$3 ~ /vi/ && $2 ~ "^s"  { print $0 }

結果為

6 six   vi
7 seven vii

列印第二個欄位等於 "three" 且第三個欄位等於 "vii" 以及所有後續行之間的行

$2 == "three", $3 == "vii" { print $0 }

結果為

3 three iii
4 four  iv
5 five  v
6 six   vi
7 seven vii

BEGIN 和 END

[編輯 | 編輯原始碼]

BEGIN 是一種特殊模式,它在第一行輸入之前匹配。類似地,END 在最後一行輸入之後匹配。

BEGIN { print "start at 3..." }
$2 == "three", $2 ~ /^e/ { print $1 }
END { print "...and end at eight" }

結果為

start at 3...
3 
4 
5 
6 
7 
8 
...and end at eight
華夏公益教科書