詳解 awk 工具的使用方法

發表於2017-05-17

【伯樂線上轉註】:awk 是一個強大的文字分析工具。它不僅是 Linux 中,也是任何環境中現有的功能最強大的資料處理引擎之一。相對於 grep 的查詢,sed的編輯,awk在其對資料分析並生成報告時,顯得尤為強大。


當你第一次拿起雙手在電腦上使用 awk 命令處理一個或者多個檔案的時候,它會依次讀取檔案的每一行內容, 然後對其進行處理,awk 命令預設從 stdio 標準輸入獲取檔案內容, awk 使用一對單引號來表示 一些可執行的指令碼程式碼,在可執行指令碼程式碼裡面,使用一對花括號來表示一段可執行程式碼塊,可以同時存在多個程式碼塊。 awk 的每個花括號內同時又可以有多個指令,每一個指令用分號分隔,awk 其實就是一個指令碼程式語言。說了這麼多,你肯定還是一臉的懵逼。你猜對了,上面這些都是廢話。先別急,客官請往下看……

awk 命令的基本格式

options 這個表示一些可選的引數選項,反正就是你愛用不用,不用可以拉到。。。 program 這個表示 awk 的可執行指令碼程式碼,這個是必須要有的。 file 這個表示 awk 需要處理的檔案,注意是純文字檔案,不是你的 mp3,也不是 mp4 啥的。。

先來一個 awk 的使用例子熱熱身

awk 命令的可執行指令碼程式碼使用單引號括起來,緊接著裡面是一對花括號,記住是 “花括號” 不是 “花姑娘”,然後花括號裡面就是一些可執行的指令碼程式碼段,當 awk 每讀取一行之後,它會依次執行雙引號裡面的每個指令碼程式碼段,在上面這個例子中, $0 表示當前行。當你執行了上面的命令之後,它會依次將 /etc/passwd 檔案的每一行內容列印輸出,你一定在想:這有個毛用,用 cat 命令也能搞定。沒錯!上面這個命令沒個毛用,請往下看。

awk 自定義分隔符

awk 預設的分割符為空格和製表符,我們可以使用 -F 引數來指定分隔符

上面的命令將 /etc/passwd 檔案中的每一行用冒號 : 分割成多個欄位,然後用 print 將第 1 列欄位的內容列印輸出

如何在 awk 中同時指定多個分隔符

比如現在有這樣一個檔案 some.log 檔案內容如下

現在我們想將上面的 some.log 檔案中按照 “水果名稱(重量)年份” 來進行分割

-F 引數中使用一對方括號來指定多個分隔符,awk 處理 some.log 檔案時就會使用 “(” 和 “)” 來對檔案的每一行進行分割。

awk 內建變數的使用

$0 這個表示文字處理時的當前行

$1 表示文字行被分隔後的第 1 個欄位列

$2 表示文字行被分割後的第 2 個欄位列

$3 表示文字行被分割後的第 3 個欄位列

$n 表示文字行被分割後的第 n 個欄位列

NR 表示檔案中的行號,表示當前是第幾行

NF 表示檔案中的當前行列的個數,類似於 mysql 資料表裡面每一條記錄有多少個欄位

FS 表示 awk 的輸入分隔符,預設分隔符為空格和製表符,你可以對其進行自定義設定

OFS 表示 awk 的輸出分隔符,預設為空格,你也可以對其進行自定義設定

FILENAME 表示當前檔案的檔名稱,如果同時處理多個檔案,它也表示當前檔名稱

比如我們有這麼一個文字檔案 fruit.txt 內容如下,我將用它來向你演示如何使用 awk 命令工具,順便活躍一下此時尷尬的氣氛。。

我們來瞧一瞧下面這些簡單到爆炸的例子,這個表示列印輸出檔案的每一整行的內容

下面這個表示列印輸出檔案的每一行的第 1 列內容

下面面這個表示列印輸出檔案的每一行的第 1 列、第 2 列和第 3 列內容

其中加入的逗號表示插入輸出分隔符,也就是預設的空格

檔案的每一行的每一列的內容除了可以用 print 命令列印輸出以外,還可以對其進行賦值

上面的例子就是表示通過對 $2 變數進行重新賦值,來隱藏每一行的第 2 列內容,並且用星號 * 來代替其輸出

在引數列表中加入一些字串或者轉義字元之類的東東

像上面這樣,你可以在 print的引數列表中加入一些字串或者轉義字元之類的東東,讓輸出的內容格式更漂亮,但一定要記住要使用雙引號。

awk 內建 NR 變數表示每一行的行號

awk 內建 NF 變數表示每一行的列數

awk 中 $NF 變數的使用

上面這個 $NF 就表示每一行的最後一列,因為 NF 表示一行的總列數,在這個檔案裡表示有 5 列,然後在其前面加上 $ 符號,就變成了 $5 ,表示第 5 列

上面 $(NF-1) 表示倒數第 2 列, $(NF-2) 表示倒數第 3 列,依次類推。

現在除了剛才說的有一個 fruit.txt 檔案之外,我們又多了一個新檔案叫 company.txt 內容如下

我們用 fruit.txt 和 company.txt 兩個檔案來向你演示 awk 同時處理多個檔案的時候有什麼效果

當你使用 awk 同時處理多個檔案的時候,它會將多個檔案合併處理,變數 FILENAME 就表示當前文字行所在的檔名稱。

看到這裡是不是感覺 awk 命令的使用方法真的是簡單到爆炸,現在不要太高興,請舉起你的雙手跟我一起搖擺。。。哦,不對!請拿起你的雙手在電腦上試一試上面這些例子。 你會知道我沒有騙你,因為講了這麼多,傻子都會了。。。—_—

BEGIN 關鍵字的使用

在指令碼程式碼段前面使用 BEGIN 關鍵字時,它會在開始讀取一個檔案之前,執行一次 BEGIN 關鍵字後面的指令碼程式碼段, BEGIN 後面的指令碼程式碼段只會執行一次,執行完之後 awk 程式就會退出

awk 指令碼中可以用多個花括號來執行多個指令碼程式碼,就像下面這樣

END 關鍵字使用方法

awk 的 END 指令和 BEGIN 恰好相反,在 awk 讀取並且處理完檔案的所有內容行之後,才會執行 END 後面的指令碼程式碼段

一定要多動手在電腦上敲一敲這些命令,對身體好。腦子是個好東西,要多用。。。

在 awk 中使用變數

可以在 awk 指令碼中宣告和使用變數

在 awk 中使用數學運算

在 awk 中,像其他程式語言一樣,它也支援一些基本的數學運算操作

上面這段指令碼表示,先宣告兩個變數 a = 12 和 b = 24,然後用 print 列印出 a 加上 b 的結果。

看到上面的輸出結果,你很可能又是一臉的懵逼,為什麼會重複輸出 4 次同樣的計算結果。所以說小時不學好,長大做IT。 知識這東西真到了要用的時候,能亮瞎別人的雙眼,好了,不廢話。請記住 awk 是針對檔案的每一行來執行一次單引號 裡面的指令碼程式碼,每讀取到一行就會執行一次,檔案裡面有多少行就會執行多少次,但 BEGIN 和 END 關鍵字後面的 指令碼程式碼除外,如果被處理的檔案中什麼都沒有,那 awk 就一次都不會執行。。。

awk 還支援其他的數學運算子

  • + 加法運算子
  • - 減法運算子
  • * 乘法運算子
  • / 除法運算子
  • % 取餘運算子

在 awk 中使用條件判斷

比如有一個檔案 company.txt 內容如下

我們要判斷檔案的第 3 列資料,也就是平均工資小於 5500 的公司,然後將其列印輸出

上面的命令結果就是平均工資小於 5500 的公司名單, $3 < 5500 表示當第 3 列欄位的內容小於 5500 的時候才會執行後面的 {print $0} 程式碼塊

awk 還有一些其他的條件操作符如下

  • < 小於
  • <= 小於或等於
  • == 等於
  • != 不等於
  • > 大於
  • >= 大於或等於
  • ~ 匹配正規表示式
  • !~ 不匹配正規表示式

使用 if 指令判斷來實現上面同樣的效果

上面表示如果第 3 列欄位小於 5500 的時候就會執行後面的 print $0,很像 C 語言和 PHP 的語法對不對。 想到這裡有一句話不知當講不當講,那就是 PHP 是世界上最好的語言。。。 我可能喝多了, 但是突然想起來我好像從來不喝酒。。。—_—

在 awk 中使用正規表示式

在 awk 中支援正規表示式的使用,如果你還對正規表示式不是很瞭解,請先停下來,上 google 去搜一下。

比如現在我們有這麼一個檔案 poetry.txt 裡面都是我寫的詩,不要問我為什麼那麼的有才華。內容如下:

使用正規表示式匹配字串 “There” ,將包含這個字串的行列印並輸出

使用正規表示式配一個包含字母 t 和字母 e ,並且 t 和 e 中間只能有任意單個字元的行

如果只想匹配單純的字串 “t.e”, 那正規表示式就是這樣的 /t\.e/ ,用反斜槓來轉義 . 符號 因為 . 在正規表示式裡面表示任意單個字元。

使用正規表示式來匹配所有以 “The” 字串開頭的行

在正規表示式中 ^ 表示以某某字元或者字串開頭。

使用正規表示式來匹配所有以 “true” 字串結尾的行

在正規表示式中 $ 表示以某某字元或者字串結尾。

又一個正規表示式例子如下

上面這個正規表示式 /m[a]t/ 表示匹配包含字元 m ,然後接著後面還要包含中間方括號中表示的單個字元 a ,最後還要包含字元 t 的行,輸出結果中只有單詞 “matter” 符合這個正規表示式的匹配。因為正規表示式 [a] 方括號中表示匹配裡面的任意單個字元。

繼續上面的一個新例子如下

這個例子中的正規表示式 /^Th[ie]/表示匹配以字串 “Thi” 或者 “The” 開頭的行,正規表示式方括號中表示匹配其中的任意單個字元。

再繼續上面的新的用法

正規表示式 /s[a-z]/ 表示匹配包含字元 s 然後後面跟著任意 a 到 z 之間的單個字元的字串,比如 “se”, “so”, “sp” 等等。

正規表示式 [] 方括號中還有一些其他用法比如下面這些

正規表示式中的星號 * 和加號 + 的使用方法

上面這個表示匹配包含字串 “god”,並且中間的字母 “o” 可以出現 0 次或者多次,比如單詞 “good” 就符合這個要求。 正規表示式中的 + 和星號原理差不多,只是加號表示任意 1 個或者 1 個以上,也就是必須至少要出現一次。

正規表示式問號 ? 的使用方法

正規表示式中的問號 ? 表示它前面的字元只能出現 0 次 或者 1 次,也就是可以不出現,也可以出現,但如果有出現也只能出現 1 次。

正規表示式中的 {} 花括號用法

花括號 {} 表示規定它前面的字元必須出現的次數,像上面這個 /go{2}d/ 就表示只匹配字串 “good”,也就是中間的字母 “o” 必須要出現 2 次。

正規表示式中的花括號還有一些其他的用法如下

正規表示式中的圓括號的用法

正規表示式中的圓括號表示將多個字元當成一個完整的物件來看待。比如 /th(in){1}king/ 就表示其中字串 “in” 必須出現 1 次。而如果不加圓括號就變成了 /thin{1}king/ 這個就表示其中字元 “n” 必須出現 1 次。

看到這裡,如果你對 poetry.txt 件中寫的詩比較熟悉,你就會發現。。。我去!這詩根本就不是我寫的。所以論多讀書是多麼的重要。我有幸借用莎士比亞的詩來向你講解如何在 awk 中使用正規表示式。現在該想想晚上吃什麼,晚上去吃火鍋。。。—_—

使用 awk 的一些總結

因為 awk 算起來也是一種程式語言,它的功能遠遠不止我們上面講的這些,awk 還有一些其他比較複雜的功能。但一般我們不建議將 awk 用的太過於複雜。通常面對一些比較複雜的場景我們還是要使用其他的一些工具,比如 shell 指令碼,Lua 等等……

相關文章