jq工具的使用
jq 命令行行為的完整規(guī)則
| 命令格式 | 行為 | 示例 | 結(jié)果 |
|---|---|---|---|
jq (無(wú)任何參數(shù)) |
顯示幫助信息 | jq |
顯示幫助文檔 |
jq <選項(xiàng)> (無(wú)過濾器) |
顯示幫助信息 | jq -cjq -n |
顯示幫助文檔 |
jq <過濾器> |
阻塞等待輸入 | jq '.'jq 'map(.id)' |
等待 STDIN |
jq <選項(xiàng)> <過濾器> |
取決于選項(xiàng): - 普通選項(xiàng):等待輸入 - -n:不等待 |
jq -c '.' → 等待jq -n '.' → 立即執(zhí)行 |
|
jq <過濾器> 文件 |
立即處理文件 | jq '.' data.json |
處理文件內(nèi)容 |
jq <選項(xiàng)> <過濾器> 文件 |
立即處理文件 | jq -c '.' data.json |
處理文件內(nèi)容 |
1. 只有選項(xiàng) → 顯示幫助
$ jq -c
jq - commandline JSON processor [version 1.6]
Usage: jq [options] <jq filter> [file...]
...
# 立即顯示幫助文檔,不阻塞
2. 只有過濾器 → 阻塞等待
$ jq '.name'
(光標(biāo)閃爍,程序掛起等待輸入)
# 需要按 Ctrl+D 結(jié)束輸入或 Ctrl+C 終止
3. 過濾器 + -n → 立即執(zhí)行
$ jq -n '.name'
null # 立即輸出結(jié)果(因?yàn)闆]有輸入)
4. 過濾器 + 文件 → 立即處理
$ jq '.name' data.json
"Alice" # 立即從文件處理
為什么這個(gè)區(qū)別很重要?
在實(shí)際腳本編寫中:
#!/bin/bash
# 危險(xiǎn):會(huì)阻塞腳本執(zhí)行!
result=$(jq '.data')
# 安全:立即生成數(shù)據(jù)
result=$(jq -n '{time: now}')
# 安全:從變量讀取
json='{"value": 42}'
result=$(jq '.value' <<< "$json")
基本操作:
jq [options] <jq filter> [file...]
[options] - 可選選項(xiàng)
-
-r:原始輸出模式 -
-c:緊湊輸出 -
-n:無(wú)輸入模式
<jq filter> - 必填過濾器
:用單引號(hào)包裹的表達(dá)式 '...'
-
'.':恒等過濾器 -
'.name':字段選擇器 -
'map(.id)':數(shù)組處理
[file...] - 可選輸入文件
-
格式:文件路徑(一個(gè)或多個(gè))
-
-
data.json:?jiǎn)蝹€(gè)文件 -
file1.json file2.json:多個(gè)文件
-
輸入jq .后阻塞,然后我鍵盤輸入a,報(bào)parse error: invalid numeric literal at line2,column 0,為啥報(bào)這個(gè)錯(cuò)誤
-
jq 進(jìn)入等待輸入狀態(tài)(因?yàn)闆]有使用
-n選項(xiàng)且沒有提供文件) -
光標(biāo)在終端閃爍,等待您輸入 JSON 數(shù)據(jù)
jq 要求輸入必須是有效的 JSON,而 a 不是合法的 JSON。有效的 JSON 值必須是:
-
字符串:
"a"(必須用雙引號(hào)包裹) -
數(shù)字:
123 -
布爾值:
true或false -
對(duì)象:
{"key": "value"} -
數(shù)組:
[1, 2, 3] -
null:
null
雖然您輸入的是字母,但 jq 的解析器是這樣工作的:
-
首先嘗試解析為數(shù)字(因?yàn)閿?shù)字是 JSON 的基本類型)
-
當(dāng)看到
a時(shí),它可能期待類似0xA的十六進(jìn)制數(shù)字 -
發(fā)現(xiàn)后面沒有有效數(shù)字字符時(shí)拋出錯(cuò)誤
1. JSON 格式要求 jq 要求輸入必須是有效的 JSON,而 a 不是合法的 JSON。有效的 JSON 值必須是: 字符串:"a"(必須用雙引號(hào)包裹) 數(shù)字:123 布爾值:true 或 false 對(duì)象:{"key": "value"} 數(shù)組:[1, 2, 3] null:null 不對(duì)吧,json不是key,value么,只輸入上面的值也不是json啊?
真正的JSON格式要求:
-
頂層必須是以下之一:
-
對(duì)象(用
{}包裹) -
數(shù)組(用
[]包裹)
-
-
值類型:
-
字符串:必須雙引號(hào)包裹
"text" -
數(shù)字:整數(shù)或浮點(diǎn)數(shù)
42,3.14 -
布爾值:
true或false -
空值:
null -
對(duì)象:
{"key": "value"} -
數(shù)組:
[1, 2, 3]
-
然JSON標(biāo)準(zhǔn)要求頂層必須是對(duì)象或數(shù)組,但jq對(duì)輸入的處理更靈活:
-
jq接受任何有效的JSON值作為輸入,包括:
-
簡(jiǎn)單值:
"string",42,true,null -
復(fù)合值:
{...},[...]
-
-
這是jq的特性,不是JSON標(biāo)準(zhǔn)的特性:
# 這些在jq中都是有效的輸入 echo '"text"' | jq . # 字符串 echo '42' | jq . # 數(shù)字 echo 'true' | jq . # 布爾值
為什么jq允許簡(jiǎn)單值?
這是jq設(shè)計(jì)者的選擇:
-
實(shí)用主義:很多場(chǎng)景只需要處理簡(jiǎn)單值
-
管道友好:便于在命令行中處理各種數(shù)據(jù)
-
符合腳本需求:例如
jq -n '1 + 1'直接計(jì)算
標(biāo)準(zhǔn)JSON vs jq輸入對(duì)比
| 類型 | 標(biāo)準(zhǔn)JSON是否有效 | jq是否接受作為輸入 |
|---|---|---|
{"key": "value"} |
? | ? |
["a", "b"] |
? | ? |
"string" |
?(頂層無(wú)效) | ? |
42 |
?(頂層無(wú)效) | ? |
true |
?(頂層無(wú)效) | ? |
null |
?(頂層無(wú)效) | ? |
a |
? | ? |
json的key必須是字符串,value是上面幾種數(shù)據(jù)類型?
JSON 格式的完整規(guī)范
-
頂層結(jié)構(gòu):
-
必須是對(duì)象(
{})或數(shù)組([]) -
不能是簡(jiǎn)單值(字符串、數(shù)字、布爾值或 null)
-
-
鍵(Key)要求:
-
必須是字符串
-
必須用雙引號(hào)包裹
-
不能是數(shù)字、布爾值或其他類型
// 正確 {"name": "Alice"} // 錯(cuò)誤 - 鍵未加引號(hào) {name: "Alice"} // 錯(cuò)誤 - 鍵是數(shù)字 {42: "answer"} -
-
值(Value)類型:
類型 示例 說(shuō)明 字符串 "text"必須雙引號(hào)包裹 數(shù)字 42,3.14整數(shù)或浮點(diǎn)數(shù) 布爾值 true,false必須小寫 數(shù)組 [1, "two", true]有序值集合 對(duì)象 {"key": "value"}鍵值對(duì)集合 null null表示空值
雖然標(biāo)準(zhǔn) JSON 要求頂層必須是對(duì)象或數(shù)組,但 jq 放寬了這個(gè)限制:
-
jq 接受簡(jiǎn)單值作為輸入:
# 這些在 jq 中有效但不符合 JSON 標(biāo)準(zhǔn) echo '"text"' | jq . # 字符串 echo '42' | jq . # 數(shù)字 echo 'true' | jq . # 布爾值 -
但鍵仍然必須遵循 JSON 規(guī)范:
# 嘗試使用無(wú)效鍵 echo '{name: "Alice"}' | jq . # 報(bào)錯(cuò):parse error: Invalid numeric literal at line 1 # 正確寫法 echo '{"name": "Alice"}' | jq .
# 查看特定主機(jī)的 facts
ansible 172.17.79.16 -i hosts -m setup -o 2>/dev/null | awk-F '=> ''{print $2}'| jq .
或者ansible 172.17.79.16 -i hosts -m setup -o 2>/dev/null | tr -d "172.17.79.16 | success => "| less
-
對(duì)于數(shù)組:使用索引訪問
.[0],.[1] -
對(duì)于對(duì)象:使用鍵名訪問
.["key"]或.key -
keys函數(shù)適用于兩種結(jié)構(gòu):-
數(shù)組 → 返回索引
-
對(duì)象 → 返回鍵名
-
-
組合使用管道
|可以構(gòu)建復(fù)雜查詢
這兩種訪問方式是 jq 處理 JSON 的核心功能,掌握它們就能高效提取和轉(zhuǎn)換 JSON 數(shù)據(jù)
the simplest filter is .,which is the identity filter
在jq工具中,.(點(diǎn)號(hào))是最簡(jiǎn)單的過濾器,稱為"identity filter"(恒等過濾器)。它的作用是將輸入的JSON數(shù)據(jù)原樣輸出,僅對(duì)格式進(jìn)行標(biāo)準(zhǔn)化處理(如美化縮進(jìn))
identity?(恒等)這一術(shù)語(yǔ)源自數(shù)學(xué)和計(jì)算機(jī)科學(xué)中的概念,指代一種不改變輸入數(shù)據(jù)的操作,詞根"ident"源于拉丁語(yǔ)"idem"(相同)48,后綴"-ity"表示性質(zhì)或狀態(tài),組合后表示"同一性"或"不變性",如同身份證(identity card)唯一對(duì)應(yīng)個(gè)人身份,區(qū)別于動(dòng)詞"identify"(識(shí)別)的動(dòng)態(tài)過程,此處強(qiáng)調(diào)靜態(tài)的"同一性"
例1:
jq '.[0] | keys' array_of_objects.json
array_of_objects.json 內(nèi)容:
[
{"id": 1, "name": "Alice", "active": true},
{"id": 2, "email": "bob@example.com"},
{"role": "admin", "permissions": ["read", "write"]}
]
-
.[0]獲取數(shù)組的第一個(gè)元素{"id":1,"name":"Alice","active":true} -
keys提取這個(gè)對(duì)象的所有鍵名(按字母排序)
例2:.[]在數(shù)組和字典(對(duì)象)中的展開不同
對(duì)象的展開:
a.json的內(nèi)容如下:
{ "id": 1, "name": "Alice", "roles": ["admin", "user"] }
命令jq '.[] | keys' a.json:
'.[]' a.json 展開的字典的value
結(jié)果:
1
Alice
["admin", "user"]
{"user": {"name": "Alice", "age": 30}, "server": {"ip": "1.1.1.1"}}
jq '.[] | keys' file.json
輸出:
["age","name"]
["ip"]
數(shù)組的展開:
假設(shè)你的file.json:
[
{
"id": 1,
"name": "Alice",
"roles": ["admin", "user"]
},
{
"id": 2,
"name": "Bob",
"email": "bob@example.com"
},
{
"company": "Tech Inc",
"country": "USA"
}
]
-
.[]:展開數(shù)組中的所有元素{"id":1,"name":"Alice","roles":["admin","user"]} {"id":2,"name":"Bob","email":"bob@example.com"} {"company":"Tech Inc","country":"USA"} -
| keys:對(duì)每個(gè)展開的對(duì)象獲取鍵名["id","name","roles"] ["id","name","email"] ["company","country"]
最終輸出:
[
"id",
"name",
"roles"
]
[
"id",
"name",
"email"
]
[
"company",
"country"
]
.[] - 數(shù)組展開運(yùn)算符
-
作用:將數(shù)組拆分為獨(dú)立的元素
-
輸入:
[元素1, 元素2, ...] -
輸出:
元素1元素2...(多個(gè)獨(dú)立 JSON 對(duì)象) -
如果輸入是對(duì)象:
{"a":1, "b":2}→ 輸出值12
jq '.object.nested_array[].property' file.json
.object # 第一層:訪問根對(duì)象的 "object" 屬性
.nested_array # 第二層:訪問 object 對(duì)象的 "nested_array" 屬性
[] # 解包操作:將 nested_array 數(shù)組展開為多個(gè)元素
.property # 第三層:訪問每個(gè)數(shù)組元素的 "property" 屬性
假設(shè)你的 file.json 內(nèi)容
{
"object": {
"nested_array": [
{
"id": 1,
"property": "value1",
"details": {"sub": "a"}
},
{
"id": 2,
"property": "value2",
"details": {"sub": "b"}
}
],
"other_field": "ignored"
},
"unrelated": "data"
}
運(yùn)行命令:
jq '.object.nested_array[].property' file.json
輸出:
"value1"
"value2"
關(guān)鍵概念解釋
-
.(根選擇器)-
起始點(diǎn),表示整個(gè) JSON 文檔的根
-
類似文件系統(tǒng)的
/根目錄
-
-
.object(屬性訪問)-
訪問根對(duì)象的
object屬性 -
等價(jià)于 JavaScript 的
data.object
-
-
.nested_array(嵌套訪問)-
訪問
object對(duì)象的nested_array屬性 -
類似
data.object.nested_array
-
-
[](數(shù)組迭代器)-
最關(guān)鍵的操作符:將數(shù)組展開為獨(dú)立的元素
-
輸入:
[ {...}, {...} ]
輸出:{...}和{...}(兩個(gè)獨(dú)立對(duì)象)
-
-
.property(葉節(jié)點(diǎn)訪問)-
從每個(gè)展開的數(shù)組元素中提取
property值 -
對(duì)每個(gè)元素執(zhí)行:
element.property
-
類比其他語(yǔ)言
| jq 表達(dá)式 | JavaScript 等價(jià) | Python 等價(jià) |
|---|---|---|
.object |
data.object |
data['object'] |
.nested_array[] |
data.object.nested_array.forEach(...) |
for item in data['object']['nested_array']: |
.property |
item.property |
item['property'] |
# 查看特定主機(jī)的 facts
ansible 172.17.79.16 -i hosts -m setup -o 2>/dev/null | awk-F '=> ''{print $2}'| jq .
或者ansible 172.17.79.16 -i hosts -m setup -o 2>/dev/null | tr -d "172.17.79.16 | success => "| less
如果ansible輸出的不是單行(比如沒有使用`-o`選項(xiàng)),那么上述命令可能會(huì)失敗,因?yàn)閍nsible默認(rèn)輸出的JSON是帶縮進(jìn)的多行格式,
而awk是按行處理的,這樣每行都會(huì)被分割,導(dǎo)致輸出多行內(nèi)容給jq,而jq期望輸入是一個(gè)完整的JSON文檔。
-
ansible ... -o-o參數(shù)使輸出為單行(關(guān)鍵!)172.17.79.16 | SUCCESS => {JSON數(shù)據(jù)} -
awk -F'=> ' '{print $2}'
以"=> "為分隔符,提取第二部分(純JSON) -
jq .
美化輸出 JSON
shell中的數(shù)組arr=(a b c d)
echo ${a[0]}
和
declare -A arr1=([0]=a [1]=b [2]=c [3]=d)
echo ${b[0]}
結(jié)果一樣,有啥區(qū)別,難道普通數(shù)組可以看作關(guān)聯(lián)數(shù)組的特殊數(shù)組?
是的,索引數(shù)組可以看作關(guān)聯(lián)數(shù)組的特殊形式(鍵為連續(xù)整數(shù)),但在 Shell 實(shí)現(xiàn)中它們是不同的數(shù)據(jù)結(jié)構(gòu):
-
索引數(shù)組:為順序訪問優(yōu)化的數(shù)組
-
關(guān)聯(lián)數(shù)組:通用的鍵值存儲(chǔ)
在您的例子中,當(dāng)使用連續(xù)整數(shù)作為關(guān)聯(lián)數(shù)組的鍵時(shí),行為確實(shí)類似于索引數(shù)組,但底層實(shí)現(xiàn)和特性仍有差異。
因X.Y和X["Y"]都行,所以
ansible 172.17.69.16 -i hosts -m setup --key-file=./ssh/id_rsa -o 2>/dev/null | \
awk -F "=> " '{print $2}'|jq '.ansible_facts.ansible_nodename'
等價(jià)于
ansible 172.17.69.16 -i hosts -m setup --key-file=./ssh/id_rsa -o 2>/dev/null | \
awk -F "=> " '{print $2}'|jq '.["ansible_facts"]["ansible_nodename"]'
.是文本對(duì)象
查看ansible_facts所有key
ansible 172.17.69.16 -i hosts -m setup --key-file=./ssh/id_rsa -o 2>/dev/null | \
awk -F "=> " '{print $2}'|jq '.[]'
ansible 172.17.69.16 -i hosts -m setup --key-file=./ssh/id_rsa -o 2>/dev/null | \
awk -F "=> " '{print $2}'|jq '.ansible_facts|keys'

浙公網(wǎng)安備 33010602011771號(hào)