AWK 通過例子來介紹
AWK 是字串操作語言,主要用於 UNIX 系統。AWK 背後的想法是建立一種在處理檔案時使用的通用語言,這種語言並不太複雜,無法理解。
AWK 還有其他一些變體,但主要概念是相同的,只是附加功能。這些其他變體是 NAWK 和 GAWK。GAWK 包含兩者的所有功能,如果你願意,NAWK 比 AWK 高出一步。
想到 AWK 最簡單的方法是考慮它有兩個主要部分。模式和行動。
可能是 AWK 最基本的例子:(參見:Hello World)
BEGIN {print "START"}
{print }
END {print "STOP" }
這裡,關鍵字 BEGIN
和 END
是模式,而動作在{}內。這個例子沒用,但實際上只需要做一些小改動就可以使它成為一個有用的函式。
BEGIN {print "File\tAuthor"}
{print $8, "\t", $3}
END {print " - DONE - "}
這裡,\t
表示 Tab 字元,用於平均輸出行邊界。 $ 8 和$ 3 類似於 Shell Scripts
中的使用,但它不使用第 3 和第 8 個引數,而是使用輸入行的第 3 和第 8 列。
因此,此示例將列印:檔案作者位於頂行,而第二行則處理檔案路徑。 $ 8 是檔案的名稱,$ 3 是所有者(當檢視目錄路徑時,這將更加清晰)。最後,底線將列印,如你所料 - 完成 -
以上示例的信用轉到 http://www.grymoire.com/Unix/Awk.html
參考檔案
來自 Greg Goebel 的 coins.txt
:
gold 1 1986 USA American Eagle
gold 1 1908 Austria-Hungary Franz Josef 100 Korona
silver 10 1981 USA ingot
gold 1 1984 Switzerland ingot
gold 1 1979 RSA Krugerrand
gold 0.5 1981 RSA Krugerrand
gold 0.1 1986 PRC Panda
silver 1 1986 USA Liberty dollar
gold 0.25 1986 USA Liberty 5-dollar piece
silver 0.5 1986 USA Liberty 50-cent piece
silver 1 1987 USA Constitution dollar
gold 0.25 1987 USA Constitution 5-dollar piece
gold 1 1988 Canada Maple Leaf
最小的理論
一般 awk 單行:
awk <awk program> <file>
要麼:
<shell-command> | awk <awk program>
<shell-command>
和 <file>
被稱為 awk 輸入。
<awk program>
是此模板後面的程式碼(單個,不是雙引號):
'BEGIN {<init actions>};
<cond1> {<program actions>};
<cond2> {<program actions>};
...
END {<final actions>}'
哪裡:
<condX>
條件通常是正規表示式/re/
,與 awk 輸入行匹配;<* actions>
是語句序列,類似於 shell 命令,配有類似 C 的結構。
``按照以下規則處理:
BEGIN ...
和END ...
是可選的,在處理 awk 輸入行之前或之後執行。- 對於 awk 輸入中的每一行,如果條件
<condN>
為 meat,則執行相關的<program actions>
塊。 {<program actions>}
預設為{print $0}
。
條件可以與標準邏輯運算子組合:
/gold/ || /USA/ && !/1986/
&&
優先於||
;
Theprint
宣告。print item1 item2
語句在 STDOUT 上列印專案。
專案可以是變數(X
,$0
),字串(hello
)或數字。
item1, item2
與 OFS
變數的值進行整理;
item1 item2
剛剛好 ! 使用 item1 " " item2
作為空格或 printf 以獲得更多功能。
變數不需要 $
,即:print myVar;
以下特殊變數內建於 awk 中:
FS
:作為欄位分隔符來分割欄位中的 awk 輸入行。我可以成為一個單一的角色,FS="c"
; 一個空字串,FS=""
(然後每個單獨的字元變成一個單獨的欄位); 一個沒有斜線的正規表示式,FS="re"
;FS=" "
代表空格和製表符的執行,是預設值。NF
:要讀取的欄位數;$1
,$2
,…:第 1 場,第 2 場。等當前輸入行,$0
:當前輸入線;NR
:當前放線號。OFS
:列印時用於整理欄位的字串。ORS
:輸出記錄分隔符,預設為換行符。RS
:輸入行(記錄)分隔符。預設為換行符。設為FS
。IGNORECASE
:正則表達時影響 FS 和 RS;
例子
通過 regexp gold
過濾行並計算它們:
# awk 'BEGIN {print "Coins"} /gold/{i++; print $0} END {print i " lines out of " NR}' coins.txt
Coins
gold 1 1986 USA American Eagle
gold 1 1908 Austria-Hungary Franz Josef 100 Korona
gold 1 1984 Switzerland ingot
gold 1 1979 RSA Krugerrand
gold 0.5 1981 RSA Krugerrand
gold 0.1 1986 PRC Panda
gold 0.25 1986 USA Liberty 5-dollar piece
gold 0.25 1987 USA Constitution 5-dollar piece
gold 1 1988 Canada Maple Leaf
9 lines out of 13
基於內部 awk 變數 NR
的預設 print $0
動作和條件:
# awk 'BEGIN {print "First 3 coins"} NR<4' coins.txt
First 3 coins
gold 1 1986 USA American Eagle
gold 1 1908 Austria-Hungary Franz Josef 100 Korona
silver 10 1981 USA ingot
使用 C 風格的 printf
格式化:
# awk '{printf ("%s \t %3.2f\n", $1, $2)}' coins.txt
gold 1.00
gold 1.00
silver 10.00
gold 1.00
gold 1.00
gold 0.50
gold 0.10
silver 1.00
gold 0.25
silver 0.50
silver 1.00
gold 0.25
gold 1.00
條件例子
awk 'NR % 6' # prints all lines except those divisible by 6
awk 'NR > 5' # prints from line 6 onwards (like tail -n +6, or sed '1,5d')
awk '$2 == "foo"' # prints lines where the second field is "foo"
awk '$2 ~ /re/' # prints lines where the 2nd field mateches the regex /re/
awk 'NF >= 6' # prints lines with 6 or more fields
awk '/foo/ && !/bar/' # prints lines that match /foo/ but not /bar/
awk '/foo/ || /bar/' # prints lines that match /foo/ or /bar/ (like grep -e 'foo' -e 'bar')
awk '/foo/,/bar/' # prints from line matching /foo/ to line matching /bar/, inclusive
awk 'NF' # prints only nonempty lines (or: removes empty lines, where NF==0)
awk 'NF--' # removes last field and prints the line
通過新增動作 {...}
,可以列印特定欄位,而不是整行,例如:
awk '$2 ~ /re/{print $3 " " $4}'
列印第二個欄位匹配正規表示式/ re /的第三和第四個欄位。
一些字串函式
substr()
功能:
# awk '{print substr($3,3) " " substr($4,1,3)}'
86 USA
08 Aus
81 USA
84 Swi
79 RSA
81 RSA
86 PRC
86 USA
86 USA
86 USA
87 USA
87 USA
88 Can
match(s, r [, arr])
返回正在發生正規表示式 r
的 s
中的位置,並設定 RSTART
和 RLENGTH
的值。如果提供了引數 arr
,則返回陣列 arr
,其中元素被設定為匹配的帶括號的子表示式。arr
的第 0 個元素匹配設定為整個正規表示式匹配。表示式 arr[n, "start"]
和 arr[n, "length"]
也提供每個匹配子字串的起始位置和長度。
更多字串函式:
sub(/regexp/, "newstring"[, target])
gsub(/regexp/, "newstring"[, target])
toupper("string")
tolower("string")
宣告
一個簡單的陳述通常是以下任何一種:
variable = expression
print [ expression-list ]
printf format [ , expression-list ]
next # skip remaining patterns on this input line
exit # skip the rest of the input
如果 stat1
和 stat2
是陳述,以下也是陳述:
{stat}
{stat1; stat2}
{stat1
stat2}
if ( conditional ) statement [ else statement ]
以下標準 C-like 是構造語句:
if ( conditional ) statement [ else statement ]
while ( conditional ) statement
for ( expression ; conditional ; expression ) statement
break # usual C meaning
continue # usual C meaning
用於列印可變長度描述元素的 C 樣式迴圈,從欄位 4 開始:
# awk '{out=""; for(i=4;i<=NF;i++){out=out" "$i}; print out}' coins.txt
USA American Eagle
Austria-Hungary Franz Josef 100 Korona
USA ingot
Switzerland ingot
RSA Krugerrand
RSA Krugerrand
PRC Panda
USA Liberty dollar
USA Liberty 5-dollar piece
USA Liberty 50-cent piece
USA Constitution dollar
USA Constitution 5-dollar piece
Canada Maple Leaf
請注意,i
初始化為 0。
如果條件和計算應用於通用欄位:
# awk '/gold/ {if($3<1980) print $0 "$" 425*$2}' coins.txt
gold 1 1908 Austria-Hungary Franz Josef 100 Korona $425
gold 1 1979 RSA Krugerrand $425
AWK 可執行指令碼
#!/usr/bin/gawk -f
# This is a comment
(pattern) {action}
...
傳遞 shell 變數
# var="hello"
# awk -v x="$var" 'BEGIN {print x}'
hello