使用 jq 基于索引字符串列表的子集 json

Subset json based on string list of indices using jq

提问人:Amadou Kone 提问时间:9/10/2022 最后编辑:peakAmadou Kone 更新时间:9/11/2022 访问量:177

问:

我有一个 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)]'

数组 json slice jq

评论


答:

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]