AWK 處理檔案

在處理「10,000 Top Passwords」的檔案時,想轉成array 資料型態存起來,檔案是:

password, 32027
123456, 25969
12345678, 8667
1234, 5786
qwerty, 5455
12345, 4523
dragon, 4321
pussy, 3945
baseball, 3739
football, 3682

第一欄是要儲存成array 的資料,就想到利用AWK 來處理,之前有用過了,不過現在有點生疏,來筆記一下,加深印象。

AWK 結構及選項

AWK 是讀取檔案或利用pipeline 的方式讀取接收到的結果,以每行為一個記錄(record)進行處理,在行中會在被區分成欄位(field),預設區隔欄位的則是空白

$ awk -F fs -v var=val 'pattern {action statements}' filename
  • -F :可以自訂區隔欄位的字元是哪一個
  • -v:則是可以設定變數
  • pattern:當讀取每行時,可以利用pattern 判斷是否符合,如果沒pattern 需要判斷可以省略
  • action statements:要進行的動作,要將執行的動作寫在{ } 大括號內

欄位

AWK 會將每行區分成欄位,要取得每個欄位的話,分別是存在$1, $2 變數中,也就是說如果有一個檔案是

30931  ??  S      0:00.01 sshd: ymhuang@pts/0 (sshd)
30932   0  Ss     0:00.01 -tcsh (tcsh)

想要得到每一行的第1欄及第3欄的話,就是取得$1, 及$3,那要取得整行則是$0

 $ awk '{print $1,$3}' result

結果:

30931 S
30932 Ss

內建變數

AWK 還有許多內建的變數,有幾個在弄得過程中有看到的

變數名稱 描述

FNR

 在輸入檔案的行數
NF  目前行的欄位數
NR  目前的讀入的行數

如果只用輸入單一檔案的話,去printFNRNR 兩個變數,會發現值根本就一樣, 原因是AWK 可以讀取不只一個檔案,所以FNRNR 還是有差別的,也就是FNR 是以一個檔案的行數,NR 則是AWK 執行時讀了幾個行數。

Pattern

Pattern 可以把它當作像if 內的判斷條件,在AWK有兩個特別的pattern 分別是:

  • BEGIN:在讀取第1行前,要執行的動作可以利用BEGIN
  • END:反之,讀取到最後一行後,要執行的動作可以用END

還有支援邏輯判斷如 &&, ||, != 等的

最後

最後來處理最前面提到的那支檔案了,先說我預期輸出的格式是陣列:

['password','123456','12345678','1234','qwerty','12345','dragon','pussy','baseball','football']

AWK 指令:

cat 10k_most_common_with_frequency.txt | awk -v nlines=$(wc -l < 10k_most_common_with_frequency.txt) -F "," 'BEGIN {nlines+=1; printf"["} {printf "x27%sx27", $1} NR!=nlines {printf ","} END {printf "]"}'

說明:

  1. 指定變數的部分,也可以把shell 執行的結果設為變數值,但是,一開始我在FreeBSD 用無法成功,最後轉到CentOS 就可以run,猜測是因為CentOS 設GNU AWK 的原因才有支援
  2. 要抓取第1 個欄位,用-F 來設定分隔號是逗號
  3. 要在第一行及最後一行分別輸出[ 及 ] 是利用BEGINEND 兩個pattern
  4. 輸出欄位用printf,格式化輸出成’password’,要把單引號(single quote) 轉成ASCII 的16進位才能printf 出來
  5. NR 則是目前讀到的行數,如果行數不等於最後一行則印出逗號

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料