提问人:Amadou Kone 提问时间:9/10/2022 最后编辑:peakAmadou Kone 更新时间:9/11/2022 访问量:177
使用 jq 基于索引字符串列表的子集 json
Subset json based on string list of indices using jq
问:
我有一个 JSON 数组,如下所示:
["a","b","c"]
我有一个 bash 变量,它是我想子集的数组索引列表
ix="0,2"
我想使用这些索引的子集,生成以下数组:jq
["a", "c"]
到目前为止,我已经能够解析成一个数组:$ix
echo '["a","b","c"]' | jq --arg ix $ix '$ix | split(",") | map(tonumber)'
但是当我尝试使用这个索引数组来子集时,我遇到了问题(以下工作都没有):["a","b","c"]
echo '["a","b","c"]' | jq --arg ix $ix '. | $ix | split(",") | map(tonumber)'
echo '["a","b","c"]' | jq --arg ix $ix '. | ($ix | split(",") | map(tonumber))'
echo '["a","b","c"]' | jq --arg ix $ix '. | [$ix | split(",") | map(tonumber)]'
echo '["a","b","c"]' | jq --arg ix $ix '. | .[$ix | split(",") | map(tonumber)]'
答:
5赞
glenn jackman
9/10/2022
#1
我会的
jq --arg ix "$ix" '
($ix | split(",") | map(tonumber)) as [$a, $b]
| .[$a:$b+1]
'
是必需的,因为数组切片操作是 from(独占)和 to(独占)+1
.[from;to]
变量赋值表达式使用表达式中的输入值,设置变量,然后将原始输入作为其输出传递。... | exp as $var | ...
另一种方法是:在 bash 中拆分 ix,并将值作为位置参数传递:
IFS=, read -ra ixs <<< "$ix"
echo '["a","b","c"]' \
| jq --jsonargs '.[$ARGS.positional[0]:$ARGS.positional[1]+1]' "${ixs[@]}"
那么,您有一个巨大的数组和大量的索引列表要提取?那么也许:
. as $some_huge_array |
reduce ($ix | split(",") | map(tonumber))[] as $i ([]; . + [$some_huge_array[$i]])
总结以下一些想法:
ix="0,3,4"
jq --argjson ixs "[$ix]" '. as $a | reduce $ixs[] as $i ([]; . + [$a[$i]])' <<END_INPUT
[1, 2, 3, 4, 5, 6, 7]
END_INPUT
[
1,
4,
5
]
正如@oguzismail指出的那样,这里不需要reduce
jq --argjson ixs "[$ix]" '[.[$ixs[]]]'
$ixs
是一个数组$ixs[]
是值流.[ $ixs[] ]
将输出每个值的输入数组的值 $ixs 作为值流- 这是一个隐式迭代
[ .[$ixs[]] ]
将上一个流收集到一个数组中。
评论
0赞
Amadou Kone
9/10/2022
谢谢格伦·杰克曼,不幸的是,我刚刚为 SO 写了一个玩具示例。在我的实际用例中,变量有数千个索引。有没有一种解决方案不涉及为每个单独的索引分配一个变量?$ix
0赞
Inian
9/10/2022
@AmadouKone glenn 展示的示例是正确的方法,如果要将 shell 变量传递给 。更好的替代方法是将索引作为 JSON 传递,例如 using 标志,然后可以直接在 JQ 过滤器中使用jq
[0, 1, 2]
--argjson
1赞
glenn jackman
9/10/2022
这可以通过 -- demo 简单地完成--argjson ixs "[$ix]"
jq -n --argjson ixs "[$ix]" '$ixs'
2赞
oguz ismail
9/10/2022
你不需要在那里减少。 会做同样的事情[.[$ixs[]]]
1赞
Logan Palanisamy
9/10/2022
#2
$ cat test.json
>> ["a", "b", "c", "d", "e" ]
$ ix="0,2"
$ jq --arg ix "$ix" '($ix | split(",") | map(tonumber)) as [$a, $b] | .[$a:$b+1]' test.json
>> [
>> "a",
>> "b",
>> "c"
>> ]
$ jq --arg ix "$ix" '($ix | split(",") | map(tonumber)) as [$a, $b] | .[$a,$b+1]' test.json
>> "a"
>> "d"
请注意 和 之间的输出有何不同。[$a:$b+1]
[$a,$b+1]
[$a:$b+1]
是数组切片,它生成一个子数组
而选择原始数组的两个单独元素。[$a,$b+1]
评论