是否可以仅通过一次过滤JQ中的整个项目数组?比较下面的代码,它们反复运行jq
:
{
"foofoo": {
"barbar": [
{
"foo": "aaaa",
"bar": 0000
},
{
"foo": "bbbb",
"bar": 1111
},
{
"foo": "cccc",
"bar": 2222
}
]
}
}
bash数组:
array=("1111" "2222")
我的代码正在运行,但效率不是很高,考虑到实际的数组大小,它使用了大量资源:
for k in "${array[@]}"; do
jq --argjson k "$k" '.foofoo.barbar |= map(select(.bar != $k))' json.json | sponge json.json
done
它不断循环遍历数组,删除不需要的条目并使用海绵再次存储相同的文件。
有什么想法可以用更简单的代码实现类似的行为?
所需的输出:
{
"foofoo": {
"barbar": [
{
"foo": "aaaa",
"bar": 0
}
]
}
}
答案 0 :(得分:2)
要显着提高性能,请使用以下jq
方法(不使用任何 shell 循环):
arr=("1111" "2222")
jq '($p | split(" ") | map(tonumber)) as $exclude
| .foofoo.barbar
|= map(select(.bar as $b
| any($exclude[]; . == $b) | not))' \
--arg p "${arr[*]}" file.json | sponge file.json
输出:
{
"foofoo": {
"barbar": [
{
"foo": "aaaa",
"bar": 0
}
]
}
}
答案 1 :(得分:1)
我很肯定有更好的方法可以做到这一点:我真的只是在jq上扔东西,直到有东西粘在墙上...
# 1. in the shell, construct a JSON object string from the array => {"bbbb":1,"cccc":1}
printf -v jsonobj '{%s}' "$(printf '"%q":1\n' "${array[@]}" | paste -sd,)"
# 2. use that to test for non-membership in the jq select function
jq --argjson o "$jsonobj" '.foofoo.barbar |= map(select((.bar|in($o)) == false))' json.json
输出
{
"foofoo": {
"barbar": [
{
"foo": "0000",
"bar": "aaaa"
}
]
}
}
您实际上没有显示所需的输出,所以我认为这就是您想要的。
答案 2 :(得分:0)
构造字典对象为有效的解决方案打开了一扇门。如果您的jq具有INDEX/2
,则可以使用以下调用:
jq --arg p "${arr[*]}" '
INDEX($p | split(" ")[]; .) as $dict
| .foofoo.barbar
|= map(select($dict[.bar|tostring] | not))'
如果您的jq没有INDEX/2
,那么现在是升级的绝佳时机;否则,您可以通过谷歌搜索来破坏其定义:
jq "def INDEX"