如何将多个对象合并为一个对象(JQ)

8
给定以下输入(这是另一个复杂查询的输出结果的简化版本):
echo '{ "a": { "b":"c", "d":"e" } }{ "a": { "b":"f", "d":"g" } }' | jq '.'
{
  "a": {
    "b": "c",
    "d": "e"
  }
}
{
  "a": {
    "b": "f",
    "d": "g"
  }
}

所期望的输出:
{
   "c": "e",
   "f": "g"
}

或者(更适合后续使用):
{
   x: {
      "c": "e",
      "f": "g"
   }
}

我真的想不出该如何做。我的真正问题当然是多个对象输入数据,我真的不知道它是否是有效的 JSON。Jq 生成并接受它,但 jshon 不行。我尝试了各种可能性,但没有一个能产生我需要的结果。我认为这是最有可能的选项。
echo '{ "a": { "b":"c", "d":"e" } }{ "a": { "b":"f", "d":"g" } }' | jq ' . | { (.a.b): .a.d }'
{
   "c": "e"
}
{
   "f": "g"
}

但是,唉。我尝试了其他的事情:
' . | { x: { (.a.b): .a.d } }'
'{ x: {} | . | add }'
'{ x: {} | . | x += }'
'{ x: {} | x += . }'
'x: {} | .x += { (.a.b): .a.d }'
'{ x: {} } | .x += { (.a.b): .a.d }'

另外一个,接近了,但没成功:
'reduce { (.a.b): .a.d } as $item ({}; . + $item)'
{
  "c": "e"
}
{
  "f": "g"
}

谁愿意给我启示?
因为@peak的帮助,所以以上用例的完整答案是...
echo '{ "a": { "b": "c", "d": "e" } }{ "a": { "b": "f", "d": "g" } }' | jq -n '{ x: [inputs | .a | { (.b): .d} ] | add }'
{
  "x": {
    "c": "e",
    "f": "g"
  }
}
1个回答

9

假设您已经安装了1.5或更高版本的jq,并且您的JSON对象在一个或多个文件中。然后,对于您的第一个期望输出,您可以简单地编写:

[inputs | .a | { (.b): .d} ] | add

这里假设您使用了-n命令行选项。我相信一旦您看到解决方案是多么简单,进一步的解释就没有必要了。
对于您期望的第二个输出,您可以将上述行包装在:
{x: _}

E.g.:

$ jq -ncf program.jq input.json
{"x":{"c":"e","f":"g"}}

p.s. 你使用 reduce 的方法是正确的,但你需要使用 -s 命令行选项。

p.p.s. 你还欠我一瓶啤酒吗?


你已经很接近了,比我到现在为止都要更接近,我必须承认这一点,但输入只是一个文件 :-( (附注:你是否要去做一个完整的板条箱?;-)) - JdeHaan
正如我所说,使用“inputs”解决方案将适用于任意数量的文件。 - peak
不行,加上分号会导致语法错误(我在Linux上)。省略它会得到{ "f": "g" },而不是{ "c": "e", "f": "g" } :-( - JdeHaan
分号是打错了,已经修复。 - peak
除了输入之外,结果仍然是 | jq '[inputs | .a | { (.b): .d} ] | add' { "f": "g" } 而不是{ "c": "e", "f": "g" }。 - JdeHaan

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