我有大约 25,000 个 JSON 文件需要验证和检查,我注意到一些文件已经重复,导致使用 Excel 将 JSON 转换为 CSV 时出现错误。
我试图删除之后的所有字符串,"version":"0.2.3"}
因为这表明 JSON 的结尾,然后再重复,"version": "0.2.3"}{"analysis": {
因此我需要保留"version": "0.2.3"}
并删除{"analysis": {
其后面的所有内容,并将这些更改应用到所有 25,000 个文件。我见过有人使用 grep 和 sed 但我自己似乎无法让它们工作。
如果有人可以提供帮助,我将不胜感激,因为手动删除文本是不可取的,所以我希望在 bash 或其他东西中有一个衬垫!
下面是我需要修复的内容(其中一个文件的精简版本),下面是所需的输出。正如您所看到的,无论出于何种原因,JSON 数据可能会在 API 使用过程中自我复制。
有问题的输入(已修剪json
):
{"analysis":{"score":3},"sample":{"completed":"2022-01-27T21:22:21Z","created":"2022-01-27T21:17:57Z","id":"220127-z5h84saffl","md5":"7871a75734af389b787bad57a3ea087d","score":3,"sha1":"58a8689ee76a46559ea56a52d20425f44c8ff601","sha256":"23c5dee027c7969aabb5828641c55a005f30fb166a5006dbe3a817f56ca0e32a"},"version":"0.2.3"}{"analysis":{"score":3},"sample":{"completed":"2022-01-27T21:22:21Z","created":"2022-01-27T21:17:57Z","id":"220127-z5h84saffl","md5":"7871a75734af389b787bad57a3ea087d","score":3,"sha1":"58a8689ee76a46559ea56a52d20425f44c8ff601","sha256":"23c5dee027c7969aabb5828641c55a005f30fb166a5006dbe3a817f56ca0e32a"},"version":"0.2.3"}
期望的输出:
{"analysis":{"score":3},"sample":{"completed":"2022-01-27T21:22:21Z","created":"2022-01-27T21:17:57Z","id":"220127-z5h84saffl","md5":"7871a75734af389b787bad57a3ea087d","score":3,"sha1":"58a8689ee76a46559ea56a52d20425f44c8ff601","sha256":"23c5dee027c7969aabb5828641c55a005f30fb166a5006dbe3a817f56ca0e32a"},"version":"0.2.3"}
答案1
使用jq
(适用于大多数类 Unix 系统),您可以从文件中提取第一个 JSON 对象并使用以下命令丢弃其余对象
jq -n 'input' file >newfile
这会生成“打印精美”的 JSON。使用该-c
选项可以获得“紧凑”输出(具有最少空白的单行)。输出写入到newfile
.
该jq
指令input
生成下一个可用的 JSON 对象。我们使用-n
( --null-input
)关闭数据的默认读取,并用于input
仅处理输入文件中的第一个对象。
对于问题中给定的数据,这会产生
{
"analysis": {
"score": 3
},
"sample": {
"completed": "2022-01-27T21:22:21Z",
"created": "2022-01-27T21:17:57Z",
"id": "220127-z5h84saffl",
"md5": "7871a75734af389b787bad57a3ea087d",
"score": 3,
"sha1": "58a8689ee76a46559ea56a52d20425f44c8ff601",
"sha256": "23c5dee027c7969aabb5828641c55a005f30fb166a5006dbe3a817f56ca0e32a"
},
"version": "0.2.3"
}
然后简单地用结果覆盖原始文件。单个文件的完整处理可能看起来像
jq -n 'input' file >newfile &&
mv newfile file
假设您的文件位于当前目录中并匹配某些模式*.json
,那么您可以在简单的 shell 循环中处理所有文件,如下所示:
for name in *.json; do
cp -- "$name" "$name.orig" &&
jq -n 'input' <"$name.orig" >"$name"
done
这与我刚才展示的有点不同,将原始内容保留在带有.orig
文件名后缀的文件中,并确保原始文件的元数据(权限等)不被更改。一旦确定这样做正确,您就可以删除带有.orig
文件名后缀的文件。
始终在正确备份的数据上进行此类测试。
您还提到将这些文件转换为 CSV,但没有提及您需要什么。假设您可能希望sample
数据为 CSV 格式,并以键作为标题:
jq -n -r 'input | .sample | keys, [.[]] | @csv' file
需要选项 ( ) 来为您提供解码后的数据,而不是 JSON字符串-r
。--raw-output
对于给定的文档,这会给你
"completed","created","id","md5","score","sha1","sha256"
"2022-01-27T21:22:21Z","2022-01-27T21:17:57Z","220127-z5h84saffl","7871a75734af389b787bad57a3ea087d",3,"58a8689ee76a46559ea56a52d20425f44c8ff601","23c5dee027c7969aabb5828641c55a005f30fb166a5006dbe3a817f56ca0e32a"
答案2
使用乐(以前称为 Perl_6)
示例输入(错误的 JSON):
~$ cat file.json
{"analysis":{"score":3},"sample":{"completed":"2022-01-27T21:22:21Z","created":"2022-01-27T21:17:57Z","id":"220127-z5h84saffl","md5":"7871a75734af389b787bad57a3ea087d","score":3,"sha1":"58a8689ee76a46559ea56a52d20425f44c8ff601","sha256":"23c5dee027c7969aabb5828641c55a005f30fb166a5006dbe3a817f56ca0e32a"},"version":"0.2.3"}{"analysis":{"score":3},"sample":{"completed":"2022-01-27T21:22:21Z","created":"2022-01-27T21:17:57Z","id":"220127-z5h84saffl","md5":"7871a75734af389b787bad57a3ea087d","score":3,"sha1":"58a8689ee76a46559ea56a52d20425f44c8ff601","sha256":"23c5dee027c7969aabb5828641c55a005f30fb166a5006dbe3a817f56ca0e32a"},"version":"0.2.3"}
示例输出(Raku 的哈希格式):
~$ cat file.json | raku -MJSON::Stream -e 'my @a; \
react whenever json-stream($*IN.Supply, [q[$], *][0],) {@a.push($_.values)}; \
"\n".print; .say for @a.[0].hash;'
sample => {completed => 2022-01-27T21:22:21Z, created => 2022-01-27T21:17:57Z, id => 220127-z5h84saffl, md5 => 7871a75734af389b787bad57a3ea087d, score => 3, sha1 => 58a8689ee76a46559ea56a52d20425f44c8ff601, sha256 => 23c5dee027c7969aabb5828641c55a005f30fb166a5006dbe3a817f56ca0e32a}
version => 0.2.3
analysis => {score => 3}
上面,可以使用 Raku 的模块读入不完整的 JSON JSON::Stream
,因为它是一个 JSON 流解析器(在到达 EOF 之前解析),所以不会验证 JSON。在这种情况下这是幸运的。使用调用从数组中删除错误的第二个元素@a.[0].hash
(@a.head.hash
也有效)。
最终的格式输出JSON
是使用to-json()
RakuJSON::Tiny
模块的命令完成的。总而言之,这就是我们所做的:
最终 JSON 输出(仅使用 Raku 模块):
~$ cat Jarvis4444.json | raku -MJSON::Stream -MJSON::Tiny -e 'my @a; \
react whenever json-stream($*IN.Supply, [q[$], *][0],) {@a.push($_.values)}; \
"\n".print; to-json(@a.[0].hash).put;'
{ "version" : "0.2.3", "sample" : { "score" : 3, "created" : "2022-01-27T21:17:57Z", "sha1" : "58a8689ee76a46559ea56a52d20425f44c8ff601", "id" : "220127-z5h84saffl", "sha256" : "23c5dee027c7969aabb5828641c55a005f30fb166a5006dbe3a817f56ca0e32a", "md5" : "7871a75734af389b787bad57a3ea087d", "completed" : "2022-01-27T21:22:21Z" }, "analysis" : { "score" : 3 } }
为了与其他答案进行比较,上面的 JSON 输出可以|
通过管道传输jq
:
{
"sample": {
"completed": "2022-01-27T21:22:21Z",
"score": 3,
"sha1": "58a8689ee76a46559ea56a52d20425f44c8ff601",
"md5": "7871a75734af389b787bad57a3ea087d",
"id": "220127-z5h84saffl",
"sha256": "23c5dee027c7969aabb5828641c55a005f30fb166a5006dbe3a817f56ca0e32a",
"created": "2022-01-27T21:17:57Z"
},
"version": "0.2.3",
"analysis": {
"score": 3
}
}
[处理多个文件:当然,@Kusalananda 的答案提供了编写 shell 循环来处理多个文件、更正/保存每个文件的充足指导]。
https://github.com/moritz/json
https://github.com/FCO/JSON-Stream
https://raku.org