我想在jq
的帮助下合并两个json数组。数组中的每个对象都包含name字段,允许我按其分组并将两个数组合并为一个。
标签
[
{
"name": "power_branch",
"description": "master"
},
{
"name": "test_branch",
"description": "main"
}
]
跑步者
[
{
"name": "power_branch",
"runner": "power",
"runner_tag": "macos"
},
{
"name": "power_branch",
"runner": "power",
"runner_tag": "ubuntu"
},
{
"name": "test_branch",
"runner": "tester",
"runner_tag": ""
},
{
"name": "development",
"runner": "dev",
"runner_tag": "ubuntu"
}
]
期望输出
[
{
"name": "power_branch",
"description": "master",
"runner": "power",
"runner_tag": "macos"
},
{
"name": "power_branch",
"description": "master",
"runner": "power",
"runner_tag": "ubuntu"
},
{
"name": "test_branch",
"description": "main",
"runner": "tester",
"runner_tag": ""
}
]
我尝试使用以下脚本,但是power_branch条目被覆盖,相反,我想要另一个具有不同runner_tag的条目
#!/usr/bin/bash
LABELS='[{"name": "power_branch","description": "master"},{"name": "test_branch","description": "main"}]'
RUNNERS='''
[
{ "name": "power_branch", "runner": "power", "runner_tag": "macos" },
{ "name": "power_branch", "runner": "power", "runner_tag": "ubuntu" },
{ "name": "test_branch", "runner": "tester", "runner_tag": "" },
{ "name": "development", "runner": "dev", "runner_tag": "ubuntu" }
]
'''
FINAL=$(jq -s '[ .[0] + .[1] | group_by(.name)[] | select(length > 1) | add]' <(echo $LABELS) <(echo $RUNNERS))
echo $FINAL
输出
[
{
"name": "power_branch",
"description": "master",
"runner": "power",
"runner_tag": "ubuntu"
},
{
"name": "test_branch",
"description": "main",
"runner": "tester",
"runner_tag": ""
}
]
发布于 2022-01-03 14:47:23
如果您有两个文件labels.json
和runners.json
,则可以使用--argjson
将后者(运行程序)读入变量中,并使用map
将由select
确定的相应字段附加到输入数组(标签)的每个元素中。
jq --argjson runners "$(cat runners.json)" '
map(.name as $name | . + ($runners[] | select(.name == $name)))
' labels.json
但是,这会将整个运行程序数组读入shell命令行空间(--argjson
使用两个字符串:一个名称和一个值),如果运行程序数组足够大,该字符串很容易溢出。
因此,与使用命令替换 "$(…)"
不同,您可以直接使用--slurpfile
读取运行程序文件,以支付另一个迭代级别[][]
的成本,或者(尽管手册在注释中说不要更多地阅读),也可以像以前一样使用只有一个迭代级别的--argfile
:
jq --slurpfile runners runners.json '
map(.name as $name | . + ($runners[][] | select(.name == $name)))
' labels.json
jq --argfile runners runners.json '
map(.name as $name | . + ($runners[] | select(.name == $name)))
' labels.json
为了避免所有这些问题,请将每个文件的建议与-n
选项一起使用input
@P峰值-n
。请注意,这要求在按顺序读取两个文件时,按此顺序提供它们。
jq -n 'input as $runners | input |
map(.name as $name | . + ($runners[] | select(.name == $name)))
' runners.json labels.json
由于第二个input
(标签)作为过滤器的主要输入直接传递(相对于存储在变量中供以后使用的运行程序),可以通过再次删除-n
选项(文件的顺序仍然重要)来进一步简化:
jq 'input as $runners |
map(.name as $name | . + ($runners[] | select(.name == $name)))
' runners.json labels.json
最后,这里还有另一种使用SQL风格运算符 INDEX
和JOIN
的方法,它们是在JQv1.6中引入的。这还使用了仅使用一个input
的技术,而且文件的顺序仍然很重要,因为我们需要运行程序数组作为过滤器的主要输入。
jq '
JOIN(INDEX(input[]; .name); .name) | map(select(.[1]) | add)
' runners.json labels.json
https://stackoverflow.com/questions/70567330
复制相似问题