【问题标题】:How to delete the last character of prior line with sed如何用sed删除前一行的最后一个字符
【发布时间】:2017-03-14 14:32:54
【问题描述】:

我正在尝试使用 sed 删除前一行的最后一个字符的行:

我有一个 json 文件:

{
"name":"John",
"age":"16",
"country":"Spain"
}

我想删除所有条目的国家/地区,为此我必须删除前一行的 json 语法的逗号。

我正在使用这种模式:

sed '/country/d' test.json
sed -n '/resolved//.$//{x;d;};1h;1!{x;p;};${x;p;}' test.json

编者注
OP 后来澄清了以下附加要求,这使一些现有答案无效:
- 应删除 多次 出现的 country 属性
- 跨越对象层次结构的所有级别
- 应该容忍空格变化

【问题讨论】:

  • 我想知道为什么sed?有很多工具能够解析 JSON。考虑使用 jqperlphp 或带有内置 JSON 解析器的东西。
  • 我更喜欢 SHELL,因为我将在 jenkins 工作中使用该命令
  • “我更喜欢 SHELL”:您可以使用一些工具从 shell 脚本中操作 json。例如,jq。

标签: json bash sed


【解决方案1】:

使用正确的 JSON 解析器,例如 jq 通常是最好的选择e(见下文),但如果安装实用程序不是一个选项,试试这个 GNU sed 命令

$ sed -zr 's/,\s*"country":[^\n]+//g' test.json
{
"name":"John",
"age":"16"
}
  • -z 将输入拆分为 NULs 的记录,在这种情况下,这意味着 整个文件 会被立即读取,从而启用跨行替换。

  • -r 启用 extended 正则表达式,以获得具有更多功能的更现代的语法。

  • s/,\n"country":\s*//g 替换所有出现的逗号,后跟一个(可能是空的)空格(可能包括换行符),然后 "country" 用空字符串直到该行的末尾,即有效地 删除匹配的字符串。

    • 请注意,这假定没有其他属性或关闭}跟随这样的country 属性在同一行。

演示基于jq的更强大的解决方案

Bertrand Martel's helpful answer 包含一个jq 解决方案,但是,它没有解决在输入对象层次结构中的任何位置替换country 属性的要求(稍后)。

在高于v1.5.2 的尚未发布的jq 版本中,将提供一个内置的walk/1 函数,它支持以下简单的解决方案:

# Walk all nodes and remove a "country" property from any object.
jq 'walk(if type == "object" then del (.country) else . end)' test.json

v1.5.2及以下,您可以自己定义walk的简化变体:

jq '
  # Define recursive function walk_objects/1 that walks all objects in the
  # hierarchy.
  def walk_objects(f): . as $in | 
    if type == "object" then
      reduce keys[] as $key
        ( {}; . + { ($key):  ($in[$key] | walk_objects(f)) } ) | f
    elif type == "array" then map( walk_objects(f) )
    else . end;
  # Walk all objects and remove a "country" property, if present.
  walk_objects(del(.country))
' test.json

【讨论】:

    【解决方案2】:

    这可能对你有用(GNU sed):

    sed 'N;s/,\s*\n\s*"country".*//;P;D' file
    

    将两行读入模式空间并删除替换字符串。

    注意允许在行的任一侧留出空格。

    【讨论】:

      【解决方案3】:

      正如之前指出的,您应该真正考虑使用 JSON 解析器来解析 JSON。

      当你说你可以 slurp 整个文件,删除换行符然后替换 相应地:

      $ sed ':a;N;$!ba;s/\n//g;s/,"country"[^}]*//' test.json
      {"name":"John","age":"16"}
      

      细分:

      :a;                 # Define label 'a'
         N;               # Append next line to pattern space
           $!ba;          # Goto 'a' unless it's the last line
      s/\n//g;            # Replace all newlines with nothing
      s/,"country"[^}]*// # Replace ',"country...' with nothing
      

      【讨论】:

        【解决方案4】:

        您可以使用像 jq 这样的 JSON 解析器来解析 json 文件。以下将返回没有country字段的文档,并将新文档写入result.json

        jq 'del(.country)' file.json > result.json
        

        【讨论】:

        猜你喜欢
        • 2018-06-04
        • 1970-01-01
        • 2018-11-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-15
        • 2014-03-05
        • 1970-01-01
        相关资源
        最近更新 更多