2015年4月19日 星期日

[linux][教學] 用grep + awk+sed處理文字資料

enter image description here
資料來源:http://animals.oreilly.com/origin-of-species/
過去處理資料可能會使用像是R之類的工具,但是最近開始k些linux的指令後,認識了awk & sed,從此愛上他們.awk和sed是linux中處理使用串流方式處理字串的工具,特色是支援pipeline(亦即可以接其他資料來源,以及將處理完的資料丟給別人處理),正規表達式,而且速度極快!平常可以用awk & sed搭配像是grep等文字工具,來處理linux中的文件檔案(特別是log檔),做一些字串的篩選和判斷.這次將用網頁log資來作為範例.

awk & sed的教學很多,一些簡單的介紹和教學可以參考鳥哥歐萊禮這本是最詳細的.有興趣深究的可以參考看看,就算不用學得很複雜,光是簡單的指令也可以省下很多工夫.

範例資料
user_id=10000;user_tel=0912333212;region=台北市
user_id=10001;region=台北市
user_id=10002;user_tel=0987654321


Grep

Grep主要拿拿來尋找字串,比如說我今天要將有user_tel的紀錄挑出來,如果用R可能就要一番苦心,但是在linux下,只要
grep user_tel file
如果當檔案很多,你不想要全部列出來只要改成
grep user_tel file | head
就可以只列出前面幾行.如果想把抓出來的檔案另存新檔,也只要
grep user_tel file > new_file
是不是比用其他軟體處理起來方便多了!


Awk

Awk用途很廣,但是比較不一樣的是可以將資料切欄位,因為log檔案使用;來分隔request欄位,比如我只想抓user_id後面的東西,該怎麼辦呢?
awk -F\; ‘{print $1}’ file
-F代表是分隔的符號, print $1代表的是用;分隔後的第幾個欄位.當原始文字檔案很大的時候,就可以用這招快速找到你要的資料(不過欄位不整齊的話,就要再想其他辦法囉~)


Sed

Sed比較常用來取代替換字串,例如今天有串資料長得像
Taipei, 0912123456, Taipei, 0921123123, Taipei, 0987123456
這樣的資料,我們會想將這樣的資料整理成這樣的格式,方便做後續分析:

Taipei, 0912123456
Taipei, 0921123123
Taipei, 0987123456

這時候只要善用sed大神 ~
echo "Taipei, 0912123456, Taipei, 0921123123, Taipei, 0987123456" | sed 's/,/\n/g'
就可以把資料依逗號切成行
Taipei
0912123456
Taipei
0921123123
Taipei
0987123456
接著我們再使用sed 'N;s/\n/,/g'將資料兩兩一組用逗號拼起來
就可以得到我們要的結果!
透過適當的pipeline,就算是處理處理大資料(1G以上的資料),也只要花三五分鐘的時間就可以完成,達到我們要的結果,雖然乍看之下語法有點難懂,但是習慣之後卻是出乎意料的直覺,再搭配pipeline,根本神器