拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 合并具有重复键的json阵列

合并具有重复键的json阵列

白鹭 - 2022-01-23 1940 0 0

我想在jq. 阵列中的每个物件都包含名称栏位,它允许我将两个阵列分组并将其合并为一个。

标签

[
  {
    "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": ""
  }
]

uj5u.com热心网友回复:

如果您有两个档案labels.jsonrunners.json,则可以--argjson使用mapselect.

jq --argjson runners "$(cat runners.json)" '
  map(.name as $name | .   ($runners[] | select(.name == $name)))
' labels.json

但是,这会将整个 runners 阵列读入您的 shell 命令列空间(--argjson需要两个字符串:一个名称和一个值),如果 runners 阵列足够大,很容易溢位。

因此,不是使用命令替换 "$(…)",您可以直接使用 runners 档案读取--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

为了规避所有这些问题,@peak建议inputfor 每个档案与-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 样式运算子的 另一种方法INDEXJOIN该方法已在 jq v1.6 中引入。这也采用了只使用一个的技术input,而且档案的顺序仍然很重要,因为我们需要 runners 阵列作为过滤器的主要输入。

jq '
  JOIN(INDEX(input[]; .name); .name) | map(select(.[1]) | add)
' runners.json labels.json
标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *