如何使用jq按键分组合并JSON对象

4
我有一个 JSON 列表,我想在命令行上合并它。
[
 {
   "ipaddress": "10.10.10.222",
   "name": "alice"
 },
 {
   "ipaddress": "10.20.20.77",
   "name": "bob"
 },
 {
   "version": "6.7",
   "name": "alice"
 },
 {
   "version": "5.2.2",
   "name": "bob"
 }
]

预期输出:

{"name": "alice", "ipaddress": "10.10.10.222", "version": "6.7"},
{"name": "bob", "ipaddress": "10.20.20.77", "version": "5.2.2"}

你好,我可以帮助你吗?谢谢。 Bernd


需要翻译的内容未提供。
2个回答

6
jq -c 'group_by(.name)[]|add' input.json

生成一个JSON对象流(即没有逗号干扰)。

更好的方法是完全避免使用group_by/1,因为它涉及排序:

def add_by(f):
  reduce .[] as $x ({}; ($x|f) as $f | .[$f] += [$x])
  | [.[] | add];

add_by(.name)

你介意解释一下 reduce 部分是如何工作的吗?我知道它创建了一个对象,其中键是 "alice" 和 "bob",这些键的值是填充有具有相应 .name 值的对象数组。但是它如何选择只有 "alice" 的对象与 "alice" 键配对呢?这让我感到困惑。谢谢! - user197693
@user197693 - 'reduce' 行通过 .name 对对象进行分组;您可以通过添加 'debug' 过滤器来查看。 - peak
我现在明白了。我不知道调试过滤器。谢谢。 - user197693

3
如果样本数据在 data.json 中,命令如下:
$ jq -Mr '[ group_by(.name)[] | add | tojson ] | join(",\n")' data.json

将会生成输出

{"name": "alice", "ipaddress": "10.10.10.222", "version": "6.7"},
{"name": "bob", "ipaddress": "10.20.20.77", "version": "5.2.2"}

然而,如果实际需要的是一个对象数组,则使用以下命令:

$ jq -M '[group_by(.name)[] | add]' data.json

生成

[
  {
    "ipaddress": "10.10.10.222",
    "name": "alice",
    "version": "6.7"
  },
  {
    "ipaddress": "10.20.20.77",
    "name": "bob",
    "version": "5.2.2"
  }
]

虽然这回答了问题,但它并不是合并数组中重复项的通用解决方案。我向每个四个元素添加了一个子数组codes: ["A", "B"]codes: ["C", "D", "E"]等等。每个新的codes属性都会覆盖之前的属性。 - Martin Bramwell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接