awk(/ɔːk/) 是 *nix 下一種強大的文本處理工具,其名稱取自三位做者 Alfred Aho,Peter Jay Weinberger,Brian Wilson Kernighan。awk 提供的功能包括不只限於正則匹配、流控制、算術運算、甚至於函數等編程語言具有的一些特性。它發行於 1977 年,已經超過了 40 歲堪稱古董級軟件。爲了更讓人能直接明白它的用途,我把它稱爲是命令行下的 Excel,其中的一些概念和 Excel 有不少類似之處。linux
在 linux 環境下咱們有一些文本處理需求時,awk 就能派上用場了,好比 nginx 的訪問日誌,文本信息去重等等。awk 能夠直接在命令行中執行好比:nginx
echo "" | awk '{print "hello world!"}'
也能夠將一些邏輯比較複雜的代碼寫到一個 awk 腳本中,而後指定腳本文件執行:git
awk -f a.awk test.txt
awk 直接在命令行中輸入和執行 awk 腳本效果是同樣的,因此如下代碼爲了便於閱讀都寫入到一個腳本文件中。
一個完整的 awk 腳本分爲三個部分:github
BEGIN{ print("BEGIN"); } { print("BODY"); } END{ print("END"); }
可是 awk 腳本要能正確執行只須要其中一個階段就行,第一個階段是 BEGIN,就是還未開始掃描輸入文本時候的預處理時間,中間 BODY 是掃描文本執行階段,awk 每掃描到輸入文本一行數據就會執行 BODY 中的腳本代碼,最後是 END,即文本掃描完成的階段,在絕大部分使用場景中咱們直接在 {} 中寫代碼就能夠了,即省略掉了 BEGIN 和 END。編程
前面已經提到,我將 awk 視爲 *nix 下的 Excel,下面提到的一些概念和 Excel 頗爲類似。對於 awk 處理的文本通常狀況下是一行一行的,好比 nginx 的日誌文件,在 awk 的視角文本的一行被視爲一條記錄(Record)行以 n 來進行劃分。在一行中經過空格又被分爲多個域(Field),這就和 Excel 的行列差很少了。因此在 awk 程序中存在 2 個全局變量 NF,NR,這就很容易理解了。數組
須要值得注意的是域的索引不是從 0 開始的,而是從 1 開始,0 是當前行的引用,經過 $n 的語法來拿到不一樣域的值。bash
{ # 當前記錄有多少個域 print("NF is:" NF); # 當前是第幾條記錄 print("NR is:" NR); # 輸出當前行的文本 print($0); # 輸出當前行的第一個域 print($1); }
以上代碼中 print 是 awk 的一個內置函數,用於輸出文本信息。在 awk 腳本中能夠經過 # 號來寫註釋。編程語言
和不少腳本程序同樣,awk 沒有嚴格的數據類型,不一樣數據類型直接能夠直接轉換。在 awk 中聲明的變量通通會成爲全局變量,因此在一處修改了變量值,腳本其餘地方也會受到影響。在流程控制上幾乎和主流編程語言徹底同樣。if-else, while 都是支持的,在後續的列子中能夠看到。函數
在命令行下經過 -v 參數還能夠給 awk 腳本傳入參數,好比:工具
echo '' | awk -v name="jiavan" '{print("hello, "name);}'
awk 內置了不少字符串處理以及數學運算方面的函數,經常使用的如:
.....
跟多使用能夠 man 一下。
awk 還內置了一些變量名:
$0 當前處理記錄 $1-$n 當前記錄的n個字段 FS 域分隔符 NF 當前記錄的域數目 NR 已經處理的記錄條數 RS 記錄分隔符 OFS 輸出字段分隔符 ORS 輸出記錄分隔符 ARGC 命令行參數個數 ARGV 命令行參數數組 FILENAME 當前輸入文件名字 IGNRECASE 記錄爲真表明忽略大小寫匹配 ARGIND 當前被處理文件的ARGV標誌符 CONVFMT 數字轉換格式 %.6g ENVIRON UNIX環境變量 ERRNO UNIX系統錯誤消息 FIELDWIDTHS 輸入字段寬度的空白分隔字符串 FNR 當前記錄數 OFMT 數字的輸出格式 %.6g RSTART 被匹配函數匹配的字符串首 RLENGTH 匹配函數匹配的字符串長度 SUBSEP \034 PROCINFO 當前運行程序進程信息數組
有如下具備重複文本的文件 name.txt。
// name.txt jiavan kellen lzy fakafang jiavan lzy pig // a.awk { ++names[$1]; } END { for (key in names) { print(key) > "./unique.txt"; } }
上方 a.awk 先遍歷文件行存入一個數組,在 awk 中數組的 key 能夠是任意數據類型,value 也能夠是任意數據類型,名稱每出現一次 +1,最後就能統計出每一個名稱出現的次數以及將全部不重複的 key 輸出到一個文件中,這裏的操做和 bash 相似。
對於輸入的文本 words.txt,咱們使用 awk 找出帶有 av
關鍵字的單詞。
// words.txt this is a test file with some key words like average and avoid --created by jiavan. // b.awk { while (match($0, /[a-zA-Z]+?av[a-zA-Z]+?/)) { print(substr($0, RSTART, RLENGTH)); $0 = substr($0, RSTART + RLENGTH); } } // result $ awk -f b.awk words.txt average avoid av jiavan
因此在 TX 遊戲中個人 ID 是 Ji**an
這樣顯示的 :-)
本文僅提供給正在拉屎的人閱讀,不作參考。
原文出處 https://github.com/Jiavan/jia... 以爲對你有幫助就給個star吧