摘要: 本文大部分內容翻譯自我開始學習AWK時看到的一篇英文文章 AWK Tutorial ,覺得對AWK入門非常有幫助,所以對其進行了粗略的翻譯,並對其中部分內容進行了刪減或者補充,希望能為對AWK感興趣的小伙伴提供一份快速入門的教程,幫助小伙伴們快速掌握AWK的基本使用方式,當然,我也是剛開始學習AWK,本文在翻譯或者補充的過程中肯定會有很多疏漏或者錯誤,希望大家能夠幫忙指正。
本文大部分內容翻譯自我開始學習AWK時看到的一篇英文文章 AWK Tutorial ,覺得對AWK入門非常有幫助,所以對其進行了粗略的翻譯,並對其中部分內容進行了刪減或者補充,希望能為對AWK感興趣的小伙伴提供一份快速入門的教程,幫助小伙伴們快速掌握AWK的基本使用方式,當然,我也是剛開始學習AWK,本文在翻譯或者補充的過程中肯定會有很多疏漏或者錯誤,希望大家能夠幫忙指正。
本文將會持續修正和更新,最新內容請參考我的 GITHUB 上的 程序猿成長計划 項目,歡迎 Star。
概述
AWK是一門解釋型的編程語言。在文本處理領域它是非常強大的,它的名字來源於它的三位作者的姓氏:Alfred Aho, Peter Weinberger 和 Brian Kernighan。
GNU/Linux發布的AWK目前由自由軟件基金會(FSF)進行開發和維護,通常也稱它為 GNU AWK。
AWK的類型
下面是幾個AWK的變體:
- AWK - 原先來源於 AT & T 實驗室的的AWK
- NAWK - AT & T 實驗室的AWK的升級版
- GAWK - 這就是GNU AWK。所有的GNU/Linux發布版都自帶GAWK,它與AWK和NAWK完全兼容
AWK的典型用途
使用AWK可以做很多任務,下面是其中一些
- 文本處理
- 輸出格式化的文本報表
- 執行算數運算
- 執行字符串操作等等
工作流
要成為AWK編程專家,你需要先知道它的內部實現機制,AWK遵循了非常簡單的工作流 - 讀取,執行和重復,下圖描述了AWK的工作流。

Read
AWK從輸入流(文件,管道或者標准輸入)中讀取一行,然后存儲到內存中。
Execute
所有的AWK命令都依次在輸入上執行。默認情況下,AWK會對每一行執行命令,我們可以通過提供模式限制這種行為。
Repeat
處理過程不斷重復,直到到達文件結尾。
程序結構
現在,讓我們先學習一下AWK的程序結構。
BEGIN 語句塊
BEGIN語句塊的語法
BEGIN {awk-commands}
BEGIN語句塊在程序開始的使用執行,它只執行一次,在這里可以初始化變量。BEGIN是AWK的關鍵字,因此它必須為大寫,注意,這個語句塊是可選的。
BODY 語句塊
BODY語句塊的語法
/pattern/ {awk-commands}
BODY語句塊中的命令會對輸入的每一行執行,我們也可以通過提供模式來控制這種行為。注意,BODY語句塊沒有關鍵字。
END 語句塊
END語句塊的語法
END {awk-commands}
END語句塊在程序的最后執行,END是AWK的關鍵字,因此必須為大寫,它也是可選的。
讓我們創建一個包含序號,學生姓名,科目名稱和得分的文件 marks.txt。
1) Amit Physics 80 2) Rahul Maths 90 3) Shyam Biology 87 4) Kedar English 85 5) Hari History 89
下面的例子中我們將會顯示文件內容,並且添加每一列的標題
$ awk 'BEGIN{printf "Sr No\tName\tSub\tMarks\n"} {print}' marks.txt
上述代碼執行后,輸出以下內容
Sr No Name Sub Marks 1) Amit Physics 80 2) Rahul Maths 90 3) Shyam Biology 87 4) Kedar English 85 5) Hari History 89
在程序的開始,AWK在BEGIN語句中打印出標題。然后再BODY語句中,它會讀取文件的每一行然后執行AWK的print命令將每一行的內容打印到標准輸出。這個過程會一直重復直到文件的結尾。
基礎語法
AWK的使用非常簡單,我們可以直接在命令行中執行AWK的命令,也可以從包含AWK命令的文本文件中執行。
AWK命令行
我們可以使用單引號在命令行中指定AWK命令
awk [options] file ...
比如我們有一個包含下面內容的文本文件 marks.txt:
1) Amit Physics 80 2) Rahul Maths 90 3) Shyam Biology 87 4) Kedar English 85 5) Hari History 89
我們可以使用下面的命令顯示該文件的完整內容
$ awk '{print}' marks.txt
AWK程序文件
我們可以使用腳本文件提供AWK命令
awk [options] -f file ....
首先,創建一個包含下面內容的文本文件 command.awk
{print}
現在,我們可以讓AWK執行該文件中的命令,這里我們實現了和上例同樣的結果
$ awk -f command.awk marks.txt
AWK標准選項
AWK支持下列命令行標准選項
-v 變量賦值選項
該選項將一個值賦予一個變量,它會在程序開始之前進行賦值,下面的例子描述了該選項的使用
$ awk -v name=Jerry 'BEGIN{printf "Name = %s\n", name}' Name = Jerry
--dump-variables[=file] 選項
該選項會輸出排好序的全局變量列表和它們最終的值到文件中,默認的文件是 awkvars.out。
$ awk --dump-variables '' $ cat awkvars.out ARGC: 1 ARGIND: 0 ARGV: array, 1 elements BINMODE: 0 CONVFMT: "%.6g" ERRNO: "" FIELDWIDTHS: "" FILENAME: "" FNR: 0 FPAT: "[^[:space:]]+" FS: " " IGNORECASE: 0 LINT: 0 NF: 0 NR: 0 OFMT: "%.6g" OFS: " " ORS: "\n" RLENGTH: 0 RS: "\n" RSTART: 0 RT: "" SUBSEP: "\034" TEXTDOMAIN: "messages"
--help 選項
打印幫助信息。
$ awk --help Usage: awk [POSIX or GNU style options] -f progfile [--] file ... Usage: awk [POSIX or GNU style options] [--] 'program' file ... POSIX options : GNU long options: (standard) -f progfile --file=progfile -F fs --field-separator=fs -v var=val --assign=var=val Short options : GNU long options: (extensions) -b --characters-as-bytes -c --traditional -C --copyright -d[file] --dump-variables[=file] -e 'program-text' --source='program-text' -E file --exec=file -g --gen-pot -h --help -L [fatal] --lint[=fatal] -n --non-decimal-data -N --use-lc-numeric -O --optimize -p[file] --profile[=file] -P --posix -r --re-interval -S --sandbox -t --lint-old -V --version
--lint[=fatal] 選項
該選項允許檢查程序的不兼容性或者模棱兩可的代碼,當提供參數 fatal的時候,它會對待Warning消息作為Error。
$ awk --lint '' /bin/ls awk: cmd. line:1: warning: empty program text on command line awk: cmd. line:1: warning: source file does not end in newline awk: warning: no program text at all!
--posix 選項
該選項開啟嚴格的POSIX兼容。
--profile[=file]選項
該選項會輸出一份格式化之后的程序到文件中,默認文件是 awkprof.out。
$ awk --profile 'BEGIN{printf"---|Header|--\n"} {print} END{printf"---|Footer|---\n"}' marks.txt > /dev/null $ cat awkprof.out # gawk 配置, 創建 Wed Oct 26 15:05:49 2016 # BEGIN 塊 BEGIN { printf "---|Header|--\n" } # 規則 { print $0 } # END 塊 END { printf "---|Footer|---\n" }
--traditional 選項
該選項會禁止所有的gawk規范的擴展。
--version 選項
輸出版本號
$ awk --version GNU Awk 3.1.7 版權所有 © 1989, 1991-2009 自由軟件基金會(FSF)。 該程序為自由軟件,你可以在自由軟件基金會發布的 GNU 通用公共許可證(GPL)第 3版或以后版本下修改或重新發布。 該程序之所以被發布是因為希望他能對你有所用處,但我們不作任何擔保。這包含 但不限於任何商業適售性以及針對特定目的的適用性的擔保。詳情參見 GNU 通用公 共許可證(GPL)。 你應該收到程序附帶的一份 GNU 通用公共許可證(GPL)。如果沒有收到,請參看 http://www.gnu.org/licenses/ 。 You have new mail in /var/spool/mail/root
基本使用示例
本部分會講述一些有用的AWK命令和它們的使用示例,所有的例子都是以下面的文本文件 marks.txt 為基礎的
1) Amit Physics 80 2) Rahul Maths 90 3) Shyam Biology 87 4) Kedar English 85 5) Hari History 89
打印某列或者字段
AWK可以只打印輸入字段中的某些列。
$ awk '{print $3 "\t" $4}' marks.txt Physics 80 Maths 90 Biology 87 English 85 History 89
在文件marks.txt中,第三列包含了科目名,第四列則是得分,上面的例子中,我們只打印出了這兩列,$3 和 $4代表了輸入記錄中的第三和第四個字段。
打印所有的行
默認情況下,AWK會打印出所有匹配模式的行
$ awk '/a/ {print $0}' marks.txt 2) Rahul Maths 90 3) Shyam Biology 87 4) Kedar English 85 5) Hari History 89
上述命令會判斷每一行中是否包含a,如果包含則打印該行,如果BODY部分缺失則默認會執行打印,因此,上述命令和下面這個是等價的
$ awk '/a/' marks.txt
打印匹配模式的列
當模式匹配成功時,默認情況下AWK會打印該行,但是也可以讓它只打印指定的字段。例如,下面的例子中,只會打印出匹配模式的第三和第四個字段。
$ awk '/a/ {print $3 "\t" $4}' marks.txt Maths 90 Biology 87 English 85 History 89
任意順序打印列
$ awk '/a/ {print $4 "\t" $3}' marks.txt 90 Maths 87 Biology 85 English 89 History
統計匹配模式的行數
$ awk '/a/{++cnt} END {print "Count = ", cnt}' marks.txt Count = 4
打印超過18個字符的行
$ awk 'length($0) > 18' marks.txt 3) Shyam Biology 87 4) Kedar English 85
內建變量
AWK提供了很多內置的變量,它們在開發AWK腳本的過程中起着非常重要的角色。
標准AWK變量
ARGC 命令行參數個數
命令行中提供的參數個數
$ awk 'BEGIN {print "Arguments =", ARGC}' One Two Three Four Arguments = 5
ARGV 命令行參數數組
存儲命令行參數的數組,索引范圍從0 - ARGC - 1。
$ awk 'BEGIN { for (i = 0; i < ARGC - 1; ++i) { printf "ARGV[%d] = %s\n", i, ARGV[i] } }' one two three four ARGV[0] = awk ARGV[1] = one ARGV[2] = two 