在處理「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 | 目前的讀入的行數 |
如果只用輸入單一檔案的話,去print 出FNR與NR 兩個變數,會發現值根本就一樣, 原因是AWK 可以讀取不只一個檔案,所以FNR 與NR 還是有差別的,也就是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 "]"}'
說明:
- 指定變數的部分,也可以把shell 執行的結果設為變數值,但是,一開始我在FreeBSD 用無法成功,最後轉到CentOS 就可以run,猜測是因為CentOS 設GNU AWK 的原因才有支援
- 要抓取第1 個欄位,用-F 來設定分隔號是逗號
- 要在第一行及最後一行分別輸出[ 及 ] 是利用BEGIN 及END 兩個pattern
- 輸出欄位用printf,格式化輸出成’password’,要把單引號(single quote) 轉成ASCII 的16進位才能printf 出來
- NR 則是目前讀到的行數,如果行數不等於最後一行則印出逗號
發佈留言