这是来 self 的 curl 的示例 JSON 响应:
{
"success": true,
"message": "jobStatus",
"jobStatus": [
{
"ID": 9,
"status": "Successful"
},
{
"ID": 2,
"status": "Successful"
},
{
"ID": 99,
"status": "Failed"
}
]
}
我想查看 ID=2 的状态。这是我试过的命令:
cat test.txt|jq --arg v "2" '.jobStatus[]|select(.ID == $v)|.status'
回复:没有
我尝试了不带引号的 2
值,但仍然没有结果。
相比之下,如果我尝试使用 literal 2
命令,它会起作用:
cat test.txt | jq '.jobStatus[]|select(.ID == 2)|.status'
回复:
"Successful"
我卡住了。谁能帮我找出问题所在?
最佳答案
jq
是数据类型感知的:
.ID
,在 JSON 输入中定义,是一个数字,但是任何通过
--arg
传递的命令行参数(比如这里的v
)总是 string(无论你是否引用该值),
因此,为了比较它们,您必须使用显式类型转换,例如 tonumber/1
:
jq --arg v '2' '.jobStatus[] | select(.ID == ($v | tonumber)) | .status' test.txt
鉴于您只在此处传递一个标量参数,以下解决方案使用--argjson
(jq
v1.5+ ) 有点矫枉过正,但它是显式类型转换的替代方案,因为传递 JSON 参数实际上传递了typed 数据:
jq --argjson v '{ "ID": 2 }' '.jobStatus[] | select(.ID == $v.ID) | .status' test.txt
peak's answer证明甚至 --argjson v 2
有效(在这种情况下与 $v
直接比较有效),这肯定是最简洁解决方案,但可能需要解释:
尽管
2
可能看起来不像 JSON,但它是:它是一个有效的 JSON 文本,包含一个值输入数字(参见json.org)。- 具体来说,
2
是一个以数字 开头的未加引号 标记,这使它成为JSON(等效于 JSON string 的值是"2"
,它必须从 shell 传递为'"2 "'
- 注意嵌入的双引号)。
- 具体来说,
因此
jq
将--argjson -v 2
解释为一个数字,并比较.ID == $ v
按预期工作(请注意,这同样适用于--argjson -v '2'
/--argjson -v "2"
,其中 shell在jq
看到值之前删除引号)。
相比之下,您使用--arg
传递的任何内容始终是按原样使用的字符串值。换句话说:
--argjson
,其目的是接受任意JSON文本作为字符串(例如'{ "ID": 2 }'
在上面的示例中)也可以用于传递数字字符串标量以强制将它们解释为数字。
同样的技术也适用于 bool 字符串true
和false
。
帽子的提示 peak感谢他的帮助。
关于json - 使用 jq --arg 传递的数字参数与 == 不匹配的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41772776/