guest@blog.cmj.tw: ~/posts $

jq


command line for JSON

jq 是一個蠻有用、也蠻有趣的 JSON 指令工具。某種程度上來說,我會把他歸類在 Domain-Specifiec Language ,也就是專門操作 JSON 的一個程式語言。最簡單的使用方式就是 jq . [FILE PATH] 來將檔案輸出成一個可讀的 JSON 格式。

透過 -R 的參數 jq 會將讀進來的檔案視為是字串,再透過 filter 處理變成相對的 JSON 內容。 而 -s 參數會將獨進來的內容視為是一個完整的 JSON 內容而非每一行處理。

Filter

jq 支援各種直覺的 filter 來操作各種 JSON 資料型態。. 可以用來代表當下的資料,而 .[] 則是代表將當下資料視為 array 來列舉:進階的使用 .[]? 則可以列舉所有內容、但如果出現不合法內容, 則不會噴錯且繼續執行。針對 array 也支援各種物件存取.[1] 與 sub-array 的操作.[0:-3]。 這種操作也可以對字串 (string) 操作而得到預期般的結果。

如果操作的是物件本身,則可以透過.attr 來存取物件 key 為 attr 的值 (value):透過.attr? 來存取則可以避免當物件沒有 attr 這個 key 時會噴錯。

Pipe

當需要將 JSON 物件做複雜的操作時 Pipe | 是一個很常使用的技巧。像是需要存取物件的階層關係時, 可以使用 .a | .b | .c 來使用。這個語法等價於 .a.b.c,而接下來的很多技巧都會使用到 pipe。

map

mapmap_value 都屬於 jq 的 語法糖 (syntax sugar) 。map 是用來列舉每個 array 的元素, 並且針對每個元素作操作。map(x) 的語法等價於 [ .[] | x ] 同理 map_value(x) 等價於 .[] |= x

reduce

reducemap 語法類似,都是對 array 物件依序做處理,然而 reduce 語法則是將上一次執行的結果, 當作是參數的一部分。像是 reduce .[] as $item (0; . + $item) 則是將 array 的內容依序加起來, 而起始內容則為是 0

Example

進階的例子則是將 CSV 檔案轉換成 JSON 的形式:執行指令 jq -Rcs '. / "\n" | map( . / "," )' 就可以將 CSV (用 , 做分隔) 的檔案轉換成 JSON 形式。