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

use*_*929 5 bash json parameter-passing jq

以下是我的curl的示例JSON响应:

{
  "success": true,
  "message": "jobStatus",
  "jobStatus": [
    {
      "ID": 9,
      "status": "Successful"
    },
    {
      "ID": 2,
      "status": "Successful"
    },
   {
      "ID": 99,
      "status": "Failed"
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

我想检查ID = 2的状态.这是我试过的命令:

cat test.txt|jq --arg v "2" '.jobStatus[]|select(.ID == $v)|.status'
Run Code Online (Sandbox Code Playgroud)

回复:没有

我试着2没有引号的价值但仍然没有结果.

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

cat test.txt | jq '.jobStatus[]|select(.ID == 2)|.status'
Run Code Online (Sandbox Code Playgroud)

响应:

"Successful"
Run Code Online (Sandbox Code Playgroud)

我被卡住了.任何人都可以帮我识别问题吗?

mkl*_*nt0 9

jq是数据类型感知:

  • .ID,如JSON输入中定义的,是一个数字,

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

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

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

鉴于你只是在这里传递一个标量参数,下面的解决方案,使用--argjson(jqv1.5 +)有点过分,但它是显式类型转换替代方法,因为传递JSON参数实际上传递了类型化数据:

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

peak的答案表明即使--argjson v 2有效(在这种情况下$v直接与作品比较),这当然是简洁的解决方案,但可能需要解释:

  • 尽管2可能看起来不像JSON,但它是:它是一个有效的JSON文本,包含一个类型为number的(参见json.org).

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

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


帽子的尖端为他的帮助达到顶峰.


pea*_*eak 6

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

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

jq --argjson v 2 '.jobStatus[] | select(.ID == $v) | .status'
Run Code Online (Sandbox Code Playgroud)

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

当然,如果您想“规范化”.ID,以便它始终被视为字符串,您可以编写:

jq --arg v 2 '.jobStatus[] | select((.ID|tostring) == $v) | .status'
Run Code Online (Sandbox Code Playgroud)