与jq一起传递的数字参数--arg与==的数据不匹配



下面是我的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,但仍然没有结果。

相比之下,如果我尝试使用文字2的命令,它会起作用:

cat test.txt | jq '.jobStatus[]|select(.ID == 2)|.status'

响应:

"Successful"

我被卡住了。有人能帮我找出问题吗?

jq是数据类型感知:

  • .ID,如JSON输入中所定义,是数字

  • 但是与--arg一起传递的任何命令行参数(例如此处的v)都是字符串

因此,为了比较它们,您必须使用显式类型转换,例如使用tonumber/1:

jq --arg v '2' '.jobStatus[] | select(.ID == ($v | tonumber)) | .status' test.txt

假设您在这里只传递标量参数,使用--argjson(jqv1.5+)的以下解决方案有点过头了,但它是显式类型转换的替代方案,因为传递JSON参数实际上传递<em]类型的>数据

jq --argjson v '{ "ID": 2 }' '.jobStatus[] | select(.ID == $v.ID) | .status' test.txt

peak的回答表明,即使--argjson v 2也能工作(在这种情况下,与$v相比直接工作),这无疑是最简洁的解决方案,但可能需要解释

  • 尽管2看起来不像JSON,但它是:它是一个有效的JSON文本,包含一个类型为数字(请参阅JSON.org)。

    • 具体来说,2是一个以数字开头的未加引号的令牌,这使得它在JSON的上下文中成为一个数字(JSON字符串-值等价于"2",它必须作为'"2"'从shell传递-注意嵌入的双引号)
  • 因此,jq--argjson -v 2解释为数字,比较.ID == $v按预期工作(请注意,这同样适用于--argjson -v '2'/--argjson -v "2",其中shell在jq看到值之前删除引号)
    相比之下,使用--arg传递的任何内容始终是按原样使用的字符串值。

  • 换言之:--argjson的目的是接受任意JSON文本作为字符串(如上例中的'{ "ID": 2 }'),也可以用于传递数字字符串标量,以强制将其解释为数字
    同样的技术也适用于布尔字符串truefalse


感谢他的帮助

假设您想检查JSON值2,您可以选择将--arg的参数转换为数字,或者将--argjson与数字参数一起使用。这些备选方案如下所示:

jq --arg v 2 '.jobStatus[] | select(.ID == ($v|tonumber) | .status' 
jq --argjson v 2 '.jobStatus[] | select(.ID == $v) | .status'

请注意,--argjson需要一个相对较新的jq版本。

当然,如果你想"正常化"。ID,使其始终被视为字符串,您可以写:

jq --arg v 2 '.jobStatus[] | select((.ID|tostring) == $v) | .status'

最新更新