利用awk進行數據分析
「AWK是一個優良的文本處理工具,Linux及Unix環境中現有的功能最強大的數據處理引擎之一。」很多數據預處理的工作,可以使用awk來完成。awk的語法結構大致是:
awk [-F 指定分隔符] "BEGIN{執行前的語句} 過濾條件 {每行的處理語句} END{處理完所有行的語句}" 文件名
以下通過一些常用的功能來說明awk的語句,需要注意:
- 單引號和雙引號不能互換,比如"{}"兩端的單引號不能用雙引號,而字元串不能用單引號
示例文件如下:
$cat OS.csvOS,Version,HitsWindows,Windows NT 10.0,1796Windows,Windows NT 6.1,567Windows,Windows 98,292Macintosh,OS X 10.10,735Macintosh,OS X 10.12.5,596Macintosh,OS X 10.10.5,453Linux,Ubuntu,1548Linux,Fedora,1139
先來查看一下文件中的第一列和第三列:
$awk -F "," "{print $1,$3}" OS.csvOS HitsWindows 1796Windows 567Windows 292Macintosh 735Macintosh 596Macintosh 453Linux 1548Linux 1139
awk是以行為單位處理文本的,$0就表示一個記錄(即整行),而$1-$N代表記錄中的第N個欄位,上面的語句意思就是:以逗號為欄位分隔符讀入文件,把每個記錄的第一個、第三個欄位列印出來。$0和$N都是awk的內建變數,常見的內建變數如下:
一、Awk內建變數表
- $0 當前記錄(這個變數中存放著整個行的內容)
- $1~$n 當前記錄的第n個欄位,欄位間由FS分隔
- FS 輸入欄位分隔符,默認是空格
- OFS 輸出欄位分隔符, 默認也是空格
- NF 當前記錄中的欄位個數,就是有多少列
- NR 已經讀出的記錄數,就是行號,從1開始,多個文件則累加
- FNR 當前記錄數,與NR不同的是,這個值會是各個文件自己的行號
- RS 輸入的記錄分隔符, 默認為換行符
- ORS 輸出的記錄分隔符,默認為換行符
- IGNORECASE 如果為真,則進行忽略大小寫的匹配
(待補充)
二、文件的過濾
上面對文件按列進行了切片,還可以對行進行過濾,例如要輸出Linux的第一列和第三列:
$awk -F "," "$1=="Linux" {print $1,$3}" OS.csvLinux 1548Linux 1139
如果要加上列名,就用到了內建變數NR:
$awk -F "," "$1=="Linux" || NR==1 {print $1,$3}" OS.csvOS HitsLinux 1548Linux 1139
增加篩選條件,並且加上每行的行號,使用內建變數NR或FNR:
$awk -F "," "$1=="Linux" && $3>1000 || NR==1 {print NR,$1,$3}" OS.csv1 OS Hits8 Linux 15489 Linux 1139
三、文件的拆分
使用重定向可以對文件進行拆分,例如按第一列進行拆分(NR!=1表示不處理表頭):
$awk "BEGIN{FS=","} NR!=1 {print >$1}" OS.csv$lsLinux Macintosh OS.csv Windows$cat LinuxLinux,Ubuntu,1548Linux,Fedora,1139
這裡使用了另一種指定輸入欄位分隔符的方式,內建變數FS,效果同-F ","是一樣的。
四、統計
下面統計所有csv文件的文件大小總和(求和):
$ls -l *.csv | awk "{sum=+$5} END{print sum}"
ls -l的第五個欄位是文件所佔用的空間(以位元組為單位)。
再回到開始的例子,統計各操作系統的點擊數(分組求和):
$awk -F "," "NR!=1 {a[$1]+=$3} END{for(i in a) print i", "a[i]}" OS.csvLinux, 2687Windows, 2655Macintosh, 1784
如果把這個語句形象地理解為python中的字典,就比較容易記憶了:a為一個字典,鍵為第一列的值,鍵的值是第三列的累加;完成所有行的處理後,把字典的鍵和值列印出來。
如果分組計數,使用自加即可:
$awk -F "," "NR!=1 {a[$1]++} END{for(i in a) print i", "a[i]}" OS.csv
五、字元串匹配
還以開始的文件為例,想要匹配帶有"Win"的記錄:
$awk -F "," "$1 ~ /Win/ ||NR==1 {print NR,$1,$3}" OFS=" " OS.csv1 OS Hits2 Windows 17963 Windows 5674 Windows 292
其中,~ 表示模式開始,如果模式取反則用!~,/ /中是模式。多個匹配條件用|分隔,例如:
$awk -F "," "$1 ~ /Win|Lin/ ||NR==1 {print NR,$1,$3}" OFS=" " OS.csv1 OS Hits2 Windows 17963 Windows 5674 Windows 2928 Linux 15489 Linux 1139
匹配了包含Win和Lin字元的記錄,如果取反則用:
$awk -F "," "$1 !~ /Win|Lin/ ||NR==1 {print NR,$1,$3}" OFS=" " OS.csv1 OS Hits5 Macintosh 7356 Macintosh 5967 Macintosh 453
如果忽略大小寫,則使用內建變數IGNORECASE=1:
$awk -F "," "{IGNORECASE=1} $1 ~ /win/ ||NR==1 {print NR,$1,$3}" OFS=" " OS.csv1 OS Hits2 Windows 17963 Windows 5674 Windows 292
參考:
AWK 簡明教程 | | 酷 殼 - CoolShell
推薦閱讀:
※泰坦尼克號倖存預測
※Excel--速成路線
※文| Fish(梁靜茹)歌詞分析
※開篇:提升對數字力的認知,將會加速實現財富自由
※Learn R | 數據預處理之dplyr包