JQ - 合并两个数组

9

我正在寻找能够合并两个数组变量(而不是文件)的JQ查询,并且还可以让第一个数组被第二个数组中较新的值覆盖。例如:

#!/bin/bash -e

firstArrayVariable='
    [
        {
            "Key": "A B",
            "Value": "1 2"
        },
        {
            "Key": "C D",
            "Value": "3 4"
        },
        {
            "Key": "E F",
            "Value": "5 6"
        },
        {
            "Key": "G H",
            "Value": "9 10"
        }
    ]
'

secondArrayVariable='
    [
        {
            "Key": "A B",
            "Value": "1 2"
        },
        {
            "Key": "C D",
            "Value": "3 4"
        },
        {
            "Key": "G H",
            "Value": "11 12"
        },
        {
            "Key": "J K",
            "Value": "15 16"
        }
    ]
'

jq \
    --compact-output \
    --raw-output \
    --arg jqSecondArrayVariable "${secondArrayVariable}" \
    '. + $jqSecondArrayVariable // empty' \
<<< "${firstArrayVariable}"

我无法使它工作并出现以下错误:

jq: error (at :19): 无法添加数组 ([{"Key":"A ...) 和字符串 ("\n [\n ...)

我期望合并后的数组结果是什么
[
    {
        "Key": "A B",
        "Value": "1 2"
    },
    {
        "Key": "C D",
        "Value": "3 4"
    },
    {
        "Key": "E F",
        "Value": "5 6"
    },
    {
        "Key": "G H",
        "Value": "11 12"
    },
    {
        "Key": "J K",
        "Value": "15 16"
    }
]

非常感谢您的帮助!

更新内容

我尝试使用@peak建议的--argjson,它可以连接数组,但无法合并两个数组。现在我得到的结果是一个包含重复对象的数组。

2个回答

11

假设有两个输入数组分别命名为firstArrsecondArr

使用 group_by()(通过关键字"Key"对对象进行分组)和 map() 函数:

jq --argjson arr1 "$firstArr" --argjson arr2 "$secondArr" -n \
'$arr1 + $arr2 | group_by(.Key) | map(.[-1])'

输出:

[
  {
    "Key": "A B",
    "Value": "1 2"
  },
  {
    "Key": "C D",
    "Value": "3 4"
  },
  {
    "Key": "E F",
    "Value": "5 6"
  },
  {
    "Key": "G H",
    "Value": "11 12"
  },
  {
    "Key": "J K",
    "Value": "15 16"
  }
]

或者在这种特定情况下,你可以使用 unique_by() 函数来应用以下技巧,以加快速度:


jq --argjson arr1 "$firstArr" --argjson arr2 "$secondArr" -n '$arr2 + $arr1 | unique_by(.Key)'

@NamNguyen,欢迎。另外,请尝试我的第二种方法(因为它更短)。 - RomanPerekhrest
是的,第二种方法也完美地运作了,而且更好、更短。非常感谢。 - Nam Nguyen
“-n”选项的目的是什么?man手册表示:“不要读入任何输入!相反,使用null作为输入运行过滤器一次。当将jq用作简单计算器或从头构建JSON数据时,这非常有用。”但我不太理解。 - panc
@panc,这意味着在这种情况下我们不从标准输入或输入文件中读取,而是使用全局、shell变量(提到了2个数组变量)。 - RomanPerekhrest

1
您应该使用--argjson; --arg将其参数解释为JSON字符串。您还需要修改jq过滤器,因为仅添加数组将导致它们连接在一起。
如需进一步指导,请参见例如通过公共键值对组合JSON

1
感谢@peak,我尝试了--argjson,它将两个数组串联起来,但无法合并它们。在我的更改后,结果是一个长重复对象数组[{"Key":"AB","Value":"12"},{"Key":"CD","Value":"34"},{"Key":"EF","Value":"56"},{"Key":"GH","Value":"910"},{"Key":"AB","Value":"12"},{"Key":"CD","Value":"34"},{"Key":"GH","Value":"1112"},{"Key":"JK","Value":"1516"}] - Nam Nguyen

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