jq 如何从 shell 变量传递 json 键

jq how to pass json keys from a shell variable

我有一个 json 文件,我正在用 jq 解析。这是文件的示例

[{
"key1":{...},
"key2":{...}
}]
[{
"key1":{...},
"key2":{...}
}]
...

每一行都是一个包含 json 的列表(我知道这在技术上不是 json 格式,但 jq 仍然适用于这样的文件)

下面的 jq 命令有效:

cat file.json | jq -r '.[] | [.key1,.key2]'

以上正确显示:

[
<value_of_key1>,<value_of_key2>
]
[
<value_of_key1>,<value_of_key2>
]

但是,我希望 .key1,.key2 是动态的,因为这些键可以更改。所以我想传递一个变量给jq。类似于:

$KEYS=.key1,.key2
cat file.json | jq -r --arg var "$KEYS" '.[] | [$var]'

但是上面是返回密钥本身:

[
".key1,.key2"
]
[
".key1,.key2"
]

为什么会这样?实现这一目标的正确命令是什么?

对我没有帮助。作为该问题的 OP,我没有收到任何错误。

获取 jq 变量的值不会导致它作为 jq 代码执行。

此外,jq 缺少获取字符串、将其编译为 jq 代码并对结果求值的功能。 (这通常被称为eval。)

因此,除了在 jq 中编写 jq 解析器和求值器之外,您还需要施加限制 and/or 接受不同的格式。

例如,

keys='[ [ "key1", "childkey" ], [ "key2", "childkey2" ] ]'  # JSON
jq --argjson keys "$keys" '.[] | [ getpath( $keys[] ) ]' file.json

keys='key1.childkey,key2.childkey2'
jq --arg keys "$keys" '
   ( ( $keys / "," ) | map( . / "." ) ) as $keys |
   .[] | [ getpath( $keys[] ) ]
' file.json

假设你有:

cat file
[{
"key1":1,
"key2":2
}]
[{
"key1":1,
"key2":2
}]

您可以像这样使用 jq 命令:

jq '.[] | [.key1,.key2]' file
[
  1,
  2
]
[
  1,
  2
]

您可以使用 -f 从文件执行过滤器,没有什么能阻止您从 shell 变量中单独创建文件。

示例:

keys=".key1"
echo ".[] | [${keys}]" >jqf

jq -f jqf file
[
  1
]
[
  1
]

或者直接将字符串构建成jq:

# note double " causing string interpolation
jq ".[] | [${keys}]" file

您可以使用 --argjson 选项和 destructuring

file.json

[{"key1":{"a":1},"key2":{"b":2}}]
[{"key1":{"c":1},"key2":{"d":2}}]
$ in='["key1","key2"]' jq -c --argjson keys "$in" '$keys as [$key1,$key2] | .[] | [.[$key1,$key2]]' file.json

输出:

[{"a":1},{"b":2}]
[{"c":1},{"d":2}]

详细说明池上的回答。

首先,这是我的答案版本:

$ in='key1.a,key2.b'; jq -c --arg keys "$in" '($keys/","|map(./".")) as $paths | .[] | [getpath($paths[])]' <<<$'[{"key1":{"a":1},"key2":{"b":2}}] [{"key1":{"a":3},"key2":{"b":4}}]'

这给出了输出

[1,2]
[3,4]

我们来试试吧。

我们有输入

[{"key1":{"a":1},"key2":{"b":2}}]
[{"key1":{"a":3},"key2":{"b":4}}]

我们要构造数组

[["key1","a"],["key2","b"]]

然后在 getpath(PATHS) 内置函数上使用它从​​我们的输入中提取值。

首先,我们得到 in shell 变量 和字符串值 key1.a,key2.b。我们称之为 $keys.

然后$keys/","给出

["key1.a","key2.b"]
["key1.a","key2.b"]

之后$keys/","|map(./".")给出了我们想要的。

[["key1","a"],["key2","b"]]
[["key1","a"],["key2","b"]]

我们称之为 $paths

现在如果我们 .[]|[getpath($paths[])] 我们从 input 中得到值等同于

[.[] | .key1.a, .key2.b]

也就是

[1,2]
[3,4]