利用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內建變數表

  1. $0 當前記錄(這個變數中存放著整個行的內容)
  2. $1~$n 當前記錄的第n個欄位,欄位間由FS分隔
  3. FS 輸入欄位分隔符,默認是空格
  4. OFS 輸出欄位分隔符, 默認也是空格
  5. NF 當前記錄中的欄位個數,就是有多少列
  6. NR 已經讀出的記錄數,就是行號,從1開始,多個文件則累加
  7. FNR 當前記錄數,與NR不同的是,這個值會是各個文件自己的行號
  8. RS 輸入的記錄分隔符, 默認為換行符
  9. ORS 輸出的記錄分隔符,默認為換行符
  10. 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包

TAG:数据分析 | 数据分析师 | 大数据 |