如何使用公共密钥合并和附加两个json文件而不丢失其他数据

如何使用公共密钥合并和附加两个json文件而不丢失其他数据,json,shell,jq,Json,Shell,Jq,我有两个json文件,其中有几个json对象。 我想在linux上使用jq和group_by(.id)合并两个json文件 实际上,我不需要使用jq,但我需要制作linux shell脚本文件 当然,我尝试了很多解决方案,但它们并不完全符合我的要求 输入1:file1.json {"id":"1234", "branch": "master", "arr":["say", "one", "more"]} {"id":"102", "branch": "master", "arr":["yes"]

我有两个json文件,其中有几个json对象。 我想在linux上使用jq和group_by(.id)合并两个json文件 实际上,我不需要使用jq,但我需要制作linux shell脚本文件

当然,我尝试了很多解决方案,但它们并不完全符合我的要求

输入1:file1.json

{"id":"1234", "branch": "master", "arr":["say", "one", "more"]}
{"id":"102", "branch": "master", "arr":["yes"]}
{"id":"1228", "branch": "master"}
输入2:file2.json

{"id":"1234", "branch": "dev", "other": "value", "arr":["what"]}
{"id":"102", "branch": "dev"}
{"id":"0806", "branch": "master"}
我所期望的是

{"id":"1234", "branch": ["master", "dev"], "other": "value", "arr":["say", "one", "more", "what"]}
{"id":"102", "branch": ["master", "dev"], "arr":["yes"]}
{"id":"1228", "branch": "master"}
{"id":"0806", "branch": "master"}
但实际输出是这样的

{"id":"1234", "branch": "dev", "other": "value", "arr":["what"]}
{"id":"102", "branch": "dev"}
{"id":"0806", "branch": "master"}

在下文中,我们使用通用函数
combine
组合两个对象,如下所述

使用此函数,并使用以下调用:

jq -n -f combine.jq --slurpfile f1 file1.json --slurpfile f2 file2.json
假设您的jq有
索引/2
,则只需编写以下内容即可获得解决方案:

INDEX( $f1[]; .id) as $d1
| INDEX( $f2[]; .id) as $d2
| reduce (($d1+$d2)|keys_unsorted)[] as $id
    ({}; .[$id] = ($d1[$id] | combine($d2[$id])) )
| .[]
也就是说,我们为两个文件中的每个文件构造一个字典,然后在相应的键处组合对象,然后生成所需的流

如果您安装的jq没有
索引/2
,那么现在是升级的好时机,但另一种方法是从builtin.jq复制其def(请参阅下面的“注释”)

联合收割机/1 在下面的jq 1.5或更高版本中,组合值的详细信息留给内部函数,
aggregate

# Combine . with obj using aggregate/2 for shared keys whose values differ
def combine($obj):

  # Combine two entities in an array-oriented fashion:
  # if both are arrays:  a + b 
  # else if a is an array: a + [b]
  # else if b is an array: [a] + b
  # else [a, b]
  def aggregate(a; b):
    if (a|type) == "array" then
      if (b|type) == "array" then a + b
      else a + [b]
      end
    else
      if (b|type) == "array" then [a] + b
      else [a, b]
      end
    end;

  if . == null then $obj
  elif $obj == null then .
  else reduce ($obj|keys_unsorted[]) as $key (.;
         if .[$key] == $obj[$key] then . 
         else .[$key] = if has($key) and ($obj|has($key))
                        then aggregate( .[$key]; $obj[$key] )
                        else .[$key] + $obj[$key]
                end
         end )
   end ;

您的shell脚本能否依赖于节点、Python、PHP、Perl等外部解释器?@fardjad实际上并不如此。Jq很熟悉。这就是我想使用jq的原因。老实说,使用其他语言并不重要。我创建了combine.jq并调用了
jq-n-f combine.jq--slurpfile f1 file1.json--slurpfile f2 file2.json
,但结果为null。combine.jq假设您运行的是jq版本1.6;如果您的jq没有INDEX/2,那么只需复制其def,例如从我将jq升级到1.6,我还尝试复制def
def INDEX($I):INDEX($I)|[0]从链接。但结果仍然为空。请勿复制
def index
!!!首先,jq1.6已经有了
def索引
;其次,
def INDEX
def INDEX
无关。太好了。也许你可以解释一下,这样其他人可以从中受益。