跟朋友相約參加了黑客松,主要是分析 SPAM 資訊,由於官方提供的是一個很大檔案的 json format,大多操作都適用 jq 指令處理,盡量不寫 code 來分析 XD
首先,只對指定欄位取出資料:
$ cat data_set.input
[
{ "field1":"1" , "field2": "2", "field3": 3, "field4" : [1, 2, 3] } ,
{ "field1":"a" , "field2": "b", "field3": 4, "field4" : [1, 2] } ,
...
}
$ < data_set.file jq '.[] | .field1 +"-" + .field2 '
"1-2"
"a-b"
...
有時會碰到資料欄位是 number ,這時會出現 string and number cannot be added 的部分,可以這樣做:
$ < data_set.input jq '.[] | .field1 +"-" + (.field3 | tostring) '
"1-3"
"a-4"
...
有時想看某個欄位個數:
$ < data_set.input jq '.[] | .field1 +"-" + (.field4 | length | tostring) '
"1-3"
"a-2"
...
接著偷懶用 awk 整理資料:
$ < data_set.file jq '.[] | .field1 +"-" + .field2 ' | awk -F'"' '{print $2}'
1-2
a-b
...
有時需要判斷數值大小後,來決定是否輸出:
$ < data_set.file awk -F'-' '{ if($2 > 10) { print $1 }}'
輸出後,可以透過 sort 跟 uniq 整理一下:
$ < data_set.file awk -F'-' '{ if($2 > 10) { print $1 }}' | sort | uniq
有時搭配 uniq -c 計算屬性後,再用 sort -n 來排序:
$ < data_set.file awk -F'-' '{ if($2 > 10) { print $1 }}' | sort | uniq -c | sort -n
這時,輸出的結果就有指定屬性從小排到大的特性,如果第 1234 個 line 開始是你要的資料,可以搭配 tail 指令取出:
$ < data_set.file awk -F'-' '{ if($2 > 10) { print $1 }}' | sort | uniq -c | sort -n | tail -n +1234
甚至,取出後再搭配 awk 把前置數字去除,只要重要結果即可:
$ < data_set.file awk -F'-' '{ if($2 > 10) { print $1 }}' | sort | uniq -c | sort -n | tail -n +1234 | awk -F ' ' '{print $2}'
最後,如果有 lookup_pattern 跟 check_data 想要比對,記得都要把兩者做 sort,就可以用 diff 跟 comm 兩個指令:
$ sort lookup_pattern > lookup_pattern.sorted
$ sort check_data > check_data.sorted
這時想要檢查沒有落在 lookup_pattern.sorted 的清單或個數:
$ diff lookup_pattern.sorted check_data.sorted | grep "<"
$ diff lookup_pattern.sorted check_data.sorted | grep -c "<"
那如果想看有 match 到的清單:
$ comm -1 -2 lookup_pattern.sorted check_data.sorted
如此一來就類似作為清單比對的動作。若比較的條件太多時,只好寫寫 python 啦:
#!/usr/bin/python
#
# input.log、p1.log、p2.log 都是以 line 為單位的資料
#
in_data = open('input.log').read().split("\n")
pattern_data1 = open('p1.log').read().split("\n")
pattern_data2 = open('p2.log').read().split("\n")
lookup1 = {}
for i in pattern_data1:
lookup1[i] = ''
lookup2 = {}
for i in pattern_data2:
lookup2[i] = ''
for i in in_data:
if i in lookup1:
print " data in lookup1"
elif i in lookup2:
print " data in lookup2 && not in lookup1"