使用jq传递的数字参数--arg与==的数据不匹配

时间:2017-01-20 21:40:53

标签: json bash parameter-passing jq

以下是我的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"

我被困住了。任何人都可以帮我确定问题吗?

2 个答案:

答案 0 :(得分:8)

jq是数据类型感知

  • .ID,在 JSON 输入中定义,是

  • 但是通过--arg传递的任何命令行参数(例如此处v)总是一个字符串(无论你是否是否引用该值,

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

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

鉴于您只在此处传递标量参数,使用--argjsonjq v1.5 +)的以下解决方案有点过分,但它是替代显式类型转换,因为传递 JSON 参数实际上传递类型数据:< / p>

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

peak's answer表明--argjson v 2有效(在这种情况下与$v比较直接工作),这肯定是简明 解决方案,但可能需要解释

  • 即使2可能看起来像,但它是:它是一个有效的JSON文本,包含的单个 >数字(见json.org)。

    • 具体而言,2未加引号的标记,以数字开头,使其成为上下文中的数字JSON (JSON 字符串 - 值等效于"2",来自shell的必须以'"2"'传递 - 请注意嵌入的双引号。 / LI>
  • 因此jq--argjson -v 2解释为数字,并且比较.ID == $v按预期工作(请注意,这同样适用于{{1} } / --argjson -v '2',其中shell在--argjson -v "2"看到值之前删除了引号 相比之下,您使用jq传递的任何内容始终是按原样使用的字符串值。

  • 换句话说:--arg,其目的是接受任意JSON文本作为字符串(例如上例中的--argjson),也可用于传递数字字符串< em> scalars 强制将其解释为数字 相同的技术也适用于布尔字符串'{ "ID": 2 }'true

peak寻求帮助的提示。

答案 1 :(得分:3)

假设您要检查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。

当然,如果你想&#34;正常化&#34; .ID这样它总是被视为字符串,你可以写:

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