Ubuntu 创建并追加键值对到一个JSON对象的文件中,每个JSON对象的值都有一个重名词

Create and append key value pairs to a file of JSON objects with a regex of each JSON object value


问题

我有一个包含json对象的大文件,每个对象都在一个新的行中。

文件例子

{"Name" :"%Hana-29-Mrs-Smith","job":"engineer"}
{"Name" :"%Mike-31-Mr-Larry","job":"marketing"}
{"Name" :"%Jhon-40-Mr-Doe","job":"engineer"}

希望的输出。

{"Name" :"%Hana-29-Mr-Smith", "f_nams":"Hana", "age":29, "title":"Mrs", "l_name":"Smith","job":"engineer"}
{"Name" :"%Mike-29-Mr-Larry", "f_nams":"Mike", "age":31, "title":"Mr", "l_name":"Larry","job":"marketing"}
{"Name" :"%Jhon-29-Mr-Smith", "f_nams":"Jhon", "age":40, "title":"Mr", "l_name":"Doe","job":"engineer"}
很高兴看到问题的标题措辞清晰,描述了确切的问题,是一个有用的问题,因为json文件可以不只是一个json对象。 有用性和清晰性+1
来自你,意味着很多。谢谢你 @SergiyKolodyazhnyy !
你带来了一个伟大的主题 @SergiyKolodyazhnyy!当获得小文件时,将这些小文件附加在一起,直到它达到一定的大小 "取决于你的硬件",然后对它运行一个shell-cmd,可能会看到一些改进。
很高兴能帮上忙! :)
答案1

对于像这样的非嵌套对象,你可以考虑使用 Miller

$ mlr --json put -S '
    @x = splitnv(substr($Name,1,-1),"-"); $f_nams = @x[1]; $age = @x[2]; $title = @x[3]; $l_name = @x[4]
  ' then reorder -e -f job file.json
{ "Name": "%Hana-29-Mrs-Smith", "f_nams": "Hana", "age": 29, "title": "Mrs", "l_name": "Smith", "job": "engineer" }
{ "Name": "%Mike-31-Mr-Larry", "f_nams": "Mike", "age": 31, "title": "Mr", "l_name": "Larry", "job": "marketing" }
{ "Name": "%Jhon-40-Mr-Doe", "f_nams": "Jhon", "age": 40, "title": "Mr", "l_name": "Doe", "job": "engineer" }
真是个好工具!速度和效率都很高。谢谢你! 我发现唯一的缺点是重码功能,一个重码语句在 regex101 中可以正常工作,但在 mlr 的重码参数中却不行
答案2

其中一种可能的方式是表现力强、程序化和清晰的(尽管脚本本身可能看起来有点冗长),就是使用Python3与 json 模块。

   #!/usr/bin/env python3
import json
import sys

with open(sys.argv[1]) as json_file:
    for line in json_file:
        json_obj = dict(json.loads(line))
        tokens = json_obj["Name"].split('-')
        extra_data = { 
            "f_nams": tokens[0].replace('%','') ,
            "age"   : tokens[1],
            "title" : tokens[2],
            "l_name": tokens[3]
        }
        joined_data = {**json_obj, **extra_data}
        print(json.dumps(joined_data))

    

它的工作方式是,我们使用一个上下文管理器 open() 来打开文件,并在完成后自动关闭。从问题中的样本数据来看,我们可以假设每个json对象都在不同的行上(注意:如果你使用的实际数据有多行json对象,你可能必须调整脚本,使用 try-except 块来读取文件,直到完整的json数据被读入一个变量)。

从这里开始,只是文本操作和Python魔法:将键 "Name "的值分成 - 个字符上的标记,放入一个列表,将标记列表放入新的字典, 用Python 3.5 ** 操作符连接两个字典,我相信这叫做 "关键字解包"(如果你使用其他版本的Python,查看链接中的替代品)。所有这些都被转换回json对象并打印在标准输出上。如果你确实需要把它保存到新的文件中,可以像 ./parse_data.py ./data.json > ./new_data.json 中那样使用shell重定向,或者如果你想在屏幕上同时看到它 ./parse_data.py ./data.json | tee ./new_data.json

它是如何工作的:

$ ./parse_data.py ./data.json 
{"Name": "%Hana-29-Mrs-Smith", "job": "engineer", "f_nams": "Hana", "age": "29", "title": "Mrs", "l_name": "Smith"}
{"Name": "%Mike-31-Mr-Larry", "job": "marketing", "f_nams": "Mike", "age": "31", "title": "Mr", "l_name": "Larry"}
{"Name": "%Jhon-40-Mr-Doe", "job": "engineer", "f_nams": "Jhon", "age": "40", "title": "Mr", "l_name": "Doe"}

$ cat ./data.json 
{"Name" :"%Hana-29-Mrs-Smith","job":"engineer"}
{"Name" :"%Mike-31-Mr-Larry","job":"marketing"}
{"Name" :"%Jhon-40-Mr-Doe","job":"engineer"}
谢谢你提供的宝贵的例子!;我是用python做的。我在考虑使用shell cmd,因为它更快。谈到有10万多行的流式日志文件。为此我在想shell会比python快
@mongotop 是的,如果速度是一个问题,那么使用C语言编写的命令行工具会更快,其中steeldriver的答案中的 Miller 应该是合适的。当然,也有一些方法可以提高python的速度,甚至使用Cython,但是为了获得最好的性能,C语言的工具是最好的