将5个或更多的JSON文件合并在一起的Shell脚本

6
我正在处理一个涉及到许多JSON文档的项目,这些文档全部存储在一个名为manifest.json的大型文件中。
这些文件的标题类似于a-11.json。请注意保留HTML标记。
{"id":"a-11",
 "name":"XN0",
  "code":"H3A8FF82820F"
  "status":"live"
} 

a-03.json

{"id":"a-03",
 "name":"PF1",
  "code":"FFFF82820F"
  "status":"live"
}

a-09.json

{"id":"a-09",
 "name":"PF1",
 "code":"FFFF82820F"
 "status":"live"
} 

我希望一个shell脚本能够按字母顺序将它们全部连接在一起,我还需要像这样包装它们: [ {json文档}, {json文档}, {json文档} ] 用逗号分隔的方括号,以便它看起来像下面的代码-
join命令只连接两个文件,所以那不起作用,我已经尝试过cat和ls的组合,但都出了点问题。我正在尝试使用Linux环境而不是MS环境。
manifest.json
[
{"id":"a-03",
 "name":"PF1",
  "code":"FFFF82820F"
  "status":"live"
},
{"id":"a-09",
 "name":"PF1",
  "code":"FFFF82820F"
  "status":"live"
}, 
{"id":"a-11",
 "name":"XN0",
  "code":"H3A8FF82820F"
  "status":"live"
}

]

命令
cat a-*.json > manifest.json

在顶部使用a-11.json文档,给我以下内容,任何帮助都将不胜感激。
[
{"id":"a-11",
 "name":"XN0",
  "code":"H3A8FF82820F"
  "status":"live"
}
{"id":"a-03",
 "name":"PF1",
  "code":"FFFF82820F"
  "status":"live"
},
{"id":"a-09",
 "name":"PF1",
  "code":"FFFF82820F"
  "status":"live"
}, 

]

2
嗯,echo '[' >manifest.json; cat a-01.json >>manifest.json; echo , >>manifest.json; cat a-02.json >>manifest.json; ..... ; echo ']' >>manifest.json?如果您不想明确指定每个a-NN.json,那么您需要一个循环。 - user3159253
输入数据不是 JSON 格式的,有逗号丢失。 - jfs
2个回答

24
您可以使用jq 工具(用于处理JSON数据):
$ jq -s '.' a-*.json > manifest.json

manifest.json:

[
  {
    "status": "live",
    "code": "H3A8FF82820F",
    "name": "XN0",
    "id": "a-11"
  },
  {
    "status": "live",
    "code": "FFFF82820F",
    "name": "PF1",
    "id": "a-03"
  },
  {
    "status": "live",
    "code": "FFFF82820F",
    "name": "PF1",
    "id": "a-09"
  }
]

在我抓取了看起来非常有价值的jq之后,它运行得很好,但为什么它会将键值对排序,以至于“moves”移到文档底部? - Richard
一个 JSON 对象是一个无序的键值对集合。1.3 版本改变了键的输入顺序。该版本在主分支中保留了顺序。如果要选择不同的顺序,例如按值排序:jq 'to_entries|sort_by(.value)|from_entries' a.json。请参见问题#318 - jfs
我对此真的感到很兴奋,但是我想要合并在一起的 JSON 文件列表大约有 600k 个文件,然后它报错说文件列表太长了。 :) - Kristian
1
@Kristian:问题与jq无关,例如cat *.json >/dev/null会产生相同的错误:bash:/bin/cat:参数列表太长。请参见Solving “mv: Argument list too long”? - jfs
@J.F.Sebastian,我同意这是一个潜在的问题,但这对我的jq使用有什么影响呢?我是这样使用它的:jq -s '.' *.json > output.json ... 在这种情况下,我应该如何插入不同的查找机制? - Kristian

9
请使用以下脚本(它使用了数组,不是所有shell都支持):
#!/bin/bash

shopt -s nullglob
declare -a jsons
jsons=(a-*.json) # ${jsons[@]} now contains the list of files to concatenate
echo '[' > manifest.json
if [ ${#jsons[@]} -gt 0 ]; then # if the list is not empty
  cat "${jsons[0]}" >> manifest.json # concatenate the first file to the manifest...
  unset jsons[0]                     # and remove it from the list
  for f in "${jsons[@]}"; do         # iterate over the rest
      echo "," >>manifest.json
      cat "$f" >>manifest.json
  done
fi
echo ']' >>manifest.json             # complete the manifest

这个工作得像梦一样,谢谢。文件按严格的字母顺序排列,以确保它们按正确的顺序出现在清单中,我所做的就是将ID更改为a-0001.json的形式,从而允许我在脚本中拥有多达1000个文档。也可以在git.bash中使用,非常好。 - Richard

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