如何通过 BASH 中的 sed 命令从 Json 文件中删除 Json 对象

Posted

技术标签:

【中文标题】如何通过 BASH 中的 sed 命令从 Json 文件中删除 Json 对象【英文标题】:How to delete a Json object from Json File by sed command in BASH 【发布时间】:2016-10-27 23:17:48 【问题描述】:

我有一个 JSON 文件,其中需要删除一个 JSON 对象。 有没有办法只使用 sed 命令删除它? 我的示例文件如下所示。


  "name": "ABC",
  "description": "XYZ",
  "versions": ,
  "json_class": "Chef::Environment",
  "chef_type": "environment",
  "default_attributes": ,
  "override_attributes": 
    "company": 
      "xyz": 
        "mailer": 
          "smtp_host": "Some IP",
          "imap_host": "Some Host",
          "imap_user": "Some UserId",
          "reply_to": "Some User Id",
          "outbound_user": "",
          "imap_mail_domain": "compute.oraclecloud.com",
          "imap_password": ""
        ,
        "logicaldomainname": ""
      
    
  

我想使用 sed 命令从文件中删除邮件对象。 请看一下,让我知道是否可以使用 sed 命令。

我这次删除的主要动机是用新的替换这个对象 mailer 对象,以便下次发布另一个 mailer 对象时,我们会将其附加到 xyz JSON 对象中。

预期输出:


  "name": "ABC",
  "description": "",
  "version": ,
  "json_class": "Chef::Environment",
  "chef_type": "environment",
  "default_attributes": ,
  "override_attributes": 
    "Company": 
      "XYZ": 
        "logicaldomainname": ""
      
    
  

【问题讨论】:

实际上 jq 由于我们机器中的一些许可规定,我们无法使用。但我们可以使用 awk, sed 绝对不合适。如果jq 不是一个选项,您应该考虑使用 Perl 或 Python:它们有很棒的 json 库。 添加了预期的输出.. 【参考方案1】:

使用sed:

sed '/\"mailer\"/,// d; /^$/d' 1.a

“从mailer删除到第一个,然后删除所有空行(你输入有一个)”。

覆盖文件(“就地”)

sed -i ...

注意:适用于多行文件(与您一样)。

【讨论】:

如果某人的用户ID是mailer? 如果“mailer”中有一个嵌套的 JSON 对象怎么办? 这非常适合删除 package.json 文件的“devDependencies”部分!谢谢!【参考方案2】:

您应该强烈考虑解决禁止jq 的许可问题:

jq 'del(.override_attributes.company.xyz.mailer) | .description=""' input.json

【讨论】:

【参考方案3】:
$ awk -v RS='^$' -v ORS= 'sub(/"mailer":[^]+,[[:space:]]+/,"")1' file

        "name": "ABC",
        "description": "",
        "versions": 

        ,
        "json_class": "Chef::Environment",
        "chef_type": "environment",
        "default_attributes": 

        ,
        "override_attributes": 
          "Company": 
            "XYZ": 
                    "logicaldomainname": ""
                      
                      
        
    

以上使用 GNU awk 进行多字符 RS,使用其他 awk,您将一次建立一行记录并在 END 部分进行处理:

$ awk -v ORS= 'rec=rec $0 RS ENDsub(/"mailer":[^]+,[[:space:]]+/,"",rec); print rec' file

        "name": "ABC",
        "description": "",
        "versions": 

        ,
        "json_class": "Chef::Environment",
        "chef_type": "environment",
        "default_attributes": 

        ,
        "override_attributes": 
          "Company": 
            "XYZ": 
                    "logicaldomainname": ""
                      
                      
        
    

【讨论】:

感谢@ED Morton,第一个对我来说很好。 第二个答案似乎正在打印预期的结果,但在原始文件中它没有改变,而第一个答案正在做同样的事情.. 不客气。给它几个小时看看你得到了什么其他答案,然后如果/当你决定接受单击它旁边的复选标记时(见***.com/help/someone-answers)。 两个脚本具有相同的行为,并且都不打算修改原始文件。 GNU awk 有一个 -i inplace 选项可以做到这一点(awk -i inplace '...script...' file),但通常使用任何 UNIX 命令 cmd 来修改您要执行的原始文件:cmd file > tmp && mv tmp file "如果某人的用户 id 是mailer?"它会从它删除到第一个,...here more spaces...,对吧?

以上是关于如何通过 BASH 中的 sed 命令从 Json 文件中删除 Json 对象的主要内容,如果未能解决你的问题,请参考以下文章

通过 Bash 从文本文件中删除空行,包括空格字符 [重复]

如何使用 sed/aws 从 json 文件中获取值?

函数内部 sed 命令中的 bash 语法错误,在命令行上工作正常

使用 bash 命令 awk sed 等从脚本中提取参数字段

BASH:如何在 sed 命令中对字符串使用 Regex Negative Lookahead?

从文本文件中删除 Unicode 字符 - sed ,其他 Bash/shell 方法