[Linux] jq 指令:好用又輕量的 JSON 工具

[Linux] jq 指令:好用又輕量的 JSON 工具

Last Updated on 2024-10-31 by OneJar

傳送門 (Table of Contents)

Togglejq 簡介安裝 jqmacOS (by homebrew)Linux排版範例資料 example1.json增加人眼可讀性 – pretty-printed壓縮資料 – compact序列化/反序列化(Serialization/Deserialization)序列化 (將 JSON 格式轉成可以傳輸的字串)反序列化 (將字串轉回 JSON 格式)取出特定欄位的值範例資料 example2.json取得某一個 key 的值取得多個 key 的值取出第二層以上的欄位值小技巧:取出字串值並清理雙引號過濾 JSON object 保留特定欄位取得第一層所有 value如果資料是物件 (Object)如果資料是陣列 (Array)取得第一層所有 key如果資料是物件 (Object)如果資料是陣列 (Array)陣列操作 – 擷取元素 (Element)範例資料 example4_array.json擷取單一元素擷取多個元素印出所有元素陣列操作 – 擷取元素 (Element) 中的特定欄位 value取特定一個欄位取多個欄位陣列操作 – 擷取元素 (Element) 中的特定欄位 value 並作字串加工map() – 對陣列元素逐一操作取出陣列中的特定 key,將結果包成陣列字串加工搭配 if-else 的範例length – 取得字串或陣列的長度取得字串長度取得陣列長度split() – 切割字串join() – 將陣列元素組合成一個字串select() – 條件過濾範例資料 example5_array.json條件示範:過濾掉 name 過長的人 (字串欄位)條件示範:過濾留下 age 大於 30 歲的人 (數字欄位)

jq 簡介

jq 是一個常用的指令工具,用於處理 JSON 格式的資料,輕量但功能強大,可以做到從 JSON 資料中擷取、轉換、篩選等操作,也可以簡單用於排版讓 JSON 資料更可讀。

這邊文章筆記常用的 jq 功能和範例。

安裝 jq

macOS (by homebrew)

brew list jq

Linux

## for Ubuntu/Debian:

sudo apt-get update

sudo apt-get install jq

## for CentOS/Red Hat:

sudo yum install jq

排版

範例資料 example1.json

❯ $ cat example1.json

{"name":"John",

"age":18}

增加人眼可讀性 – pretty-printed

$ cat example1.json | jq # 或 `cat example1.json | jq .` 亦可

{

"name": "John",

"age": 18

}

壓縮資料 – compact

濾掉多餘的換行、空白:

$ cat example1.json | jq -c

{"name":"John","age":18}

序列化/反序列化(Serialization/Deserialization)

不同作業系統或程式語言,可能使用不同的內部表示方式,為了解決資料互通問題,所以需要序列化。序列化(Serialization)是將資料結構或物件,轉換成可被解讀的格式,可以存儲在檔案中或者在網絡上傳輸,在不同系統或環境之間互通。

JSON 序列化後會是一段字串,jq 中也提供了 2 個跟序列化/反序列化有關的參數:

Option

Description

-R

序列化 (將 JSON 格式轉成可以傳輸的字串)

-r

反序列化 (將字串轉回 JSON 格式)

序列化 (將 JSON 格式轉成可以傳輸的字串)

## 範例資料

❯ $ cat example1.json

{"name":"John",

"age":18}

## 序列化用法

❯ $ cat example1.json | jq -R

"{\"name\":\"John\","

"\"age\":18}"

## 小技巧:如果想要緊實美觀一點,可以先壓縮再序列化

❯ $ cat example1.json | jq -c | jq -R

"{\"name\":\"John\",\"age\":18}"

反序列化 (將字串轉回 JSON 格式)

## 序列化過的範例資料

❯ $ cat example_serialization.txt

"{\"name\":\"John\",\"age\":18}"

## 如果沒有先反序列化,直接解析沒用,只會被當普通字串

❯ $ cat example_serialization.txt | jq

"{\"name\":\"John\",\"age\":18}"

## 反序列化用法

❯ $ cat example_serialization.txt | jq -r

{"name":"John","age":18}

## 小技巧:反序列化再排版

❯ $ cat example_serialization.txt | jq -r | jq

{

"name": "John",

"age": 18

}

取出特定欄位的值

範例資料 example2.json

❯ $ cat example2.json

{"name": "John",

"age": 18,

"job": null,

"skills": ["Java", "C#", "Node"],

"address":{"country": "Taiwan", "city": "Taipie", "district": "Xinyi"}}

取得某一個 key 的值

兩種寫法都可以:

❯ $ cat example2.json | jq .name

❯ $ cat example2.json | jq '.["name"]'

"John"

如果 key 不存在,會回 null:

❯ $ cat example2.json | jq .aaa

null

如果 key 存在但 value 是 null,也是回傳 null:

❯ $ cat example2.json | jq .job

null

取得多個 key 的值

❯ $ cat example2.json | jq '.name, .age, .skills, .aaa'

❯ $ cat example2.json | jq '.["name", "age", "skills", "aaa"]'

"John"

18

[

"Java",

"C#",

"Node"

]

null

可以把結果包成一個陣列,方便後續繼續做更多處理:

❯ $ cat example2.json | jq '[.["name", "age", "skills", "aaa"]]'

[

"John",

18,

[

"Java",

"C#",

"Node"

],

null

]

取出第二層以上的欄位值

這兩種寫法都可以:

❯ $ cat example2.json | jq .address.city

❯ $ cat example2.json | jq '.["address"]["city"]'

"Taipie"

小技巧:取出字串值並清理雙引號

❯ $ cat example2.json | jq .name

"John"

❯ $ cat example2.json | jq .name | sed 's/"//g'

John

# 感謝網友 rocky zhang 補充,也可以利用 -r 參數達到目的

❯ $ cat example2.json | jq .name -r

John

過濾 JSON object 保留特定欄位

❯ $ cat example2.json | jq '{name, skills}'

{

"name": "John",

"skills": [

"Java",

"C#",

"Node"

]

}

取得第一層所有 value

如果資料是物件 (Object)

基本用法:

❯ $ cat example2.json | jq '.[]'

"John"

18

null

[

"Java",

"C#",

"Node"

]

{

"country": "Taiwan",

"city": "Taipie",

"district": "Xinyi"

}

將結果用陣列包起來:

❯ $ cat example2.json | jq [.[]]

[

"John",

18,

null,

[

"Java",

"C#",

"Node"

],

{

"country": "Taiwan",

"city": "Taipie",

"district": "Xinyi"

}

]

如果資料是陣列 (Array)

## 範例資料

❯ $ cat example3_array.json

[{"name": "Rubio","age": 32}, {"name": "Jokic","age": 28}]

## 效果

❯ $ cat example3_array.json | jq .[]

{

"name": "Rubio",

"age": 32

}

{

"name": "Jokic",

"age": 28

}

取得第一層所有 key

如果資料是物件 (Object)

會自動用一個陣列包起來:

❯ $ cat example2.json | jq keys

[

"address",

"age",

"job",

"name",

"skills"

]

如果資料是陣列 (Array)

陣列的 key 只是流水號,意義不大:

## 範例資料

❯ $ cat example3_array.json

[{"name": "Rubio","age": 32}, {"name": "Jokic","age": 28}]

## 效果

❯ $ cat example3_array.json | jq keys

[

0,

1

]

陣列操作 – 擷取元素 (Element)

範例資料 example4_array.json

❯ $ cat example4_array.json

[{"name":"person1","age":11},{"name":"person2","age":22},{"name":"person3","age":33},{"name":"person4","age":44}]

擷取單一元素

指定陣列元素的 index:

❯ $ cat example4_array.json | jq .[1]

{

"name": "person2",

"age": 22

}

如果擷取到不存在的 index,回傳 null:

❯ $ cat example4_array.json | jq .[10]

null

擷取多個元素

可以指定多個 index:

❯ $ cat example4_array.json | jq .[1,3]

{

"name": "person2",

"age": 22

}

{

"name": "person4",

"age": 44

}

或是指定一個 index 範圍,注意這裡列印的結果已經有用陣列包起來:

❯ $ cat example4_array.json | jq .[1:3] # 不含 element[3]

[

{

"name": "person2",

"age": 22

},

{

"name": "person3",

"age": 33

}

]

印出所有元素

❯ $ cat example4_array.json | jq .[]

{

"name": "person1",

"age": 11

}

{

"name": "person2",

"age": 22

}

{

"name": "person3",

"age": 33

}

{

"name": "person4",

"age": 44

}

陣列操作 – 擷取元素 (Element) 中的特定欄位 value

取特定一個欄位

以下 3 種寫法都可以:

❯ $ cat example4_array.json | jq .[].name

❯ $ cat example4_array.json | jq '.[]["name"]'

❯ $ cat example4_array.json | jq '.[]|.name'

"person1"

"person2"

"person3"

"person4"

如果想將結果包成新的陣列:

❯ $ cat example4_array.json | jq '[.[].name]'

❯ $ cat example4_array.json | jq '[.[]["name"]]'

❯ $ cat example4_array.json | jq '[.[]|.name]'

[

"person1",

"person2",

"person3",

"person4"

]

也可以用類似過濾的方式,將結果包成新的物件陣列:

❯ $ cat example4_array.json | jq '.[]|={name}'

[

{

"name": "person1"

},

{

"name": "person2"

},

{

"name": "person3"

},

{

"name": "person4"

}

]

取多個欄位

基本用法,單純逐一印出欄位的 value:

❯ $ cat example4_array.json | jq '.[]|.name, .age'

"person1"

11

"person2"

22

"person3"

33

"person4"

44

上面寫法即使用陣列包起來,來自同一個 element 的 value 並不會 group,如果要額外處理並不好處理:

❯ $ cat example4_array.json | jq '[.[]|.name, .age]'

[

"person1",

11,

"person2",

22,

"person3",

33,

"person4",

44

]

如果希望來自同一個 element 的 value 有 group 效果,可以這樣寫:

❯ $ cat example4_array.json | jq '.[]|[.name, .age]'

[

"person1",

11

]

[

"person2",

22

]

[

"person3",

33

]

[

"person4",

44

]

陣列操作 – 擷取元素 (Element) 中的特定欄位 value 並作字串加工

以下 3 種寫法都可以:

❯ $ cat example4_array.json | jq '"Hi " + .[]["name"]'

❯ $ cat example4_array.json | jq '"Hi " + (.[]["name"])'

❯ $ cat example4_array.json | jq '"Hi \(.[]["name"])"' # (注意要用雙引號將整個 expression 包圍起來)

"Hi person1"

"Hi person2"

"Hi person3"

"Hi person4"

map() – 對陣列元素逐一操作

jq 支援一些函數功能,其中 map() 函數可以對 Array 的每一項 Element 逐一操作,最後合併結果,在某些場景應用很強大。

取出陣列中的特定 key,將結果包成陣列

這和上面的 cat example4_array.json | jq '[.[].name]' 效果是類似的,只是用 map() 的語法更簡潔易懂:

❯ $ cat example4_array.json | jq 'map(.name)'

[

"person1",

"person2",

"person3",

"person4"

]

字串加工

❯ $ cat example4_array.json | jq 'map("Hi " + .name)'

[

"Hi person1",

"Hi person2",

"Hi person3",

"Hi person4"

]

搭配 if-else 的範例

可以做更豐富的判斷應用,例如:

❯ $ echo '[0, 1, 2, 3]' | jq 'map(if . == 0 then "零" elif . == 1 then "壹" elif . == 2 then "貳" else "其他" end)'

[

"零",

"壹",

"貳",

"其他"

]

length – 取得字串或陣列的長度

length 可以用來取得長度:

字串: 字元長度

陣列: element 數

取得字串長度

❯ $ echo '{"url":"onejar99.com", "name":"OneJar 的隧道"}' | jq '.url|length'

12

取得陣列長度

❯ $ cat example4_array.json

[{"name":"person1","age":11},{"name":"person2","age":22},{"name":"person3","age":33},{"name":"person4","age":44}]

❯ $ cat example4_array.json | jq '.|length'

4

split() – 切割字串

❯ $ echo '"Rubio,Jokic,Jeremy"' | jq 'split(",")'

[

"Rubio",

"Jokic",

"Jeremy"

]

join() – 將陣列元素組合成一個字串

$ echo '["Rubio" ,"Jokic" ,"Jeremy"]' | jq '.|join(",")'

"Rubio,Jokic,Jeremy"

select() – 條件過濾

select() 常常搭配 map() 使用,做到動態條件過濾,只列印符合條件的 element。

範例資料 example5_array.json

❯ $ cat example5_array.json

[{"name":"Rubio","age":32},{"name":"Jokic","age":28},{"name":"Jeremy","age":34}]

條件示範:過濾掉 name 過長的人 (字串欄位)

❯ $ cat example5_array.json | jq 'map(select(.name|length <= 5))'

[

{

"name": "Rubio",

"age": 32

},

{

"name": "Jokic",

"age": 28

}

]

條件示範:過濾留下 age 大於 30 歲的人 (數字欄位)

❯ $ cat example5_array.json | jq 'map(select(.age|. > 30))'

[

{

"name": "Rubio",

"age": 32

},

{

"name": "Jeremy",

"age": 34

}

]

No related posts.

黄金推荐

手机云旅游app大全排行
365bet怎么注册

手机云旅游app大全排行

✨ 07-11 💎 价值: 3490
俄罗斯最受欢迎的交友软件有哪些?
sport365

俄罗斯最受欢迎的交友软件有哪些?

✨ 06-27 💎 价值: 4989
网站优化的五大效果及其实现方法
sport365

网站优化的五大效果及其实现方法

✨ 07-09 💎 价值: 3665