bash 合并 JSON 数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/42011086/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 15:42:05  来源:igfitidea点击:

Merge Arrays of JSON

arraysjsonbashjq

提问by Waffy

So my objective is to merge json files obtain this format:

所以我的目标是合并 json 文件以获得这种格式:

{
  "title": "NamesBook",
  "list": [
    {
      "name": "Ajay"
    },
    {
      "name": "Al"
    }
  ]
}

And I have files that look like this format:

我有看起来像这种格式的文件:

blahblah.json

blahblah.json

{
  "title": "NamesBook",
  "list": [
    {
      "name": "Ajay"
    }
  ]
}

blueblue.json

蓝蓝.json

{
  "title": "NamesBook",
  "list": [
    {
      "name": "Al"
    }
  ]
}

I can store the list array of all my names in a variable with the following:

我可以将我所有名字的列表数组存储在一个变量中,如下所示:

x = jq -s '.[].list' *.json

And then I was planning on appending the variable to an empty array in a file I created, out.json, which looks like this:

然后我计划将变量附加到我创建的文件 out.json 中的空数组中,如下所示:

{
  "type": "NamesBook",
  "list": []
}

However, when my script runs over the line

但是,当我的脚本越过该行时

jq '.list[] += "$x"' out.json'

It brings up a jq error:

它带来了一个 jq 错误:

Cannot iterate over null.

无法迭代 null。

Even when I add a random element, the same error shows up. Tips on how I should proceed? Are there other tools in jq to help achieve merging arrays?

即使我添加了一个随机元素,也会出现同样的错误。关于我应该如何进行的提示?jq 中是否还有其他工具可以帮助实现合并数组?

回答by zeppelin

You can merge your files with add(jq 1.3+):

您可以使用add(jq 1.3+)合并文件:

jq -s '.[0].list=[.[].list|add]|.[0]' *.json

or flatten(jq 1.5+):

展平(jq 1.5+):

jq -s '.[0].list=([.[].list]|flatten)|.[0]' *.json

[.[].list]- creates an array of all "list" arrays

[.[].list]- 创建一个包含所有“列表”数组的数组

 [
  [
    {
      "name": "Ajay"
    }
  ],
  [
    {
      "name": "Al"
    }
  ]
]

[.[].list]|flatten- flattenit (or .[].list|add- addall the arrays together)

[.[].list]|flatten-展平它(或.[].list|add-所有数组加在一起)

[
  {
    "name": "Ajay"
  },
  {
    "name": "Al"
  }
]

.[0].list=([.[].list]|flatten)|.[0]- replace the first "list" with the merged one, output it.

.[0].list=([.[].list]|flatten)|.[0]- 用合并的列表替换第一个“列表”,输出它。

{
  "title": "NamesBook",
  "list": [
    {
      "name": "Ajay"
    },
    {
      "name": "Al"
    }
  ]
}

回答by Jeff Mercado

Assuming every file will have the same titleand you're simply combining the listcontents, you could do this:

假设每个文件都相同,title并且您只是将list内容组合在一起,您可以这样做:

$ jq 'reduce inputs as $i (.; .list += $i.list)' blahblah.json blueblue.json

This just takes the first item and adds to its list, the list of all the other inputs.

这只是获取第一项并将所有其他输入的列表添加到其列表中。

回答by peak

The OP did not specify what should happen if there are objects for which .title is not "NamesBook". If the intent is to select objects with .title equal to "NamesBook", one could write:

如果存在 .title 不是“NamesBook”的对象,OP 没有指定应该发生什么。如果目的是选择 .title 等于“NamesBook”的对象,可以这样写:

map(select(.title == "NamesBook"))
| {title: .[0].title, list: map( .list ) | add}

This assumes that jq is invoked with the -s option.

这假设 jq 是使用 -s 选项调用的。

Incidentally, addis the way to go here: simple and fast.

顺便说一句,add这里的方法是:简单快捷。

回答by Jannis Ioannou

Let me also provide just what the title asks for, because I'm sure a lot of people that stepped on this question look for something simpler:

让我也提供标题所要求的内容,因为我相信很多遇到这个问题的人都在寻找更简单的东西:

echo -e '["a","b"]\n["c","d"]' | jq '.[]' | jq -s