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]
我有一个 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"
]
为什么会这样?实现这一目标的正确命令是什么?
获取 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]