【问题标题】:How to add lines after a pattern using sed如何使用 sed 在模式后添加线条
【发布时间】:2018-04-15 12:51:03
【问题描述】:

在shell脚本中,如何在某个模式之后添加行?假设我有以下文件,我想在block 1blk 2 之后添加两行。

abc
def

[block 1]
    apples = 3
    grapes = 4

[blk 2]
    banana = 2
    apples = 3

[block 1][blk 2] 将出现在文件中。

我期望的输出如下。

abc
def

[block 1]
    oranges = 5
    pears = 2
    apples = 3
    grapes = 4

[blk 2]
    oranges = 5
    pears = 2
    banana = 2
    apples = 3

我想用sed 来做这件事。我尝试了以下命令,但它在我的 Mac 上不起作用。我检查了theseposts,但我找不到我做错了什么。

$sed -i '/\[block 1\]/a\n\toranges = 3\n\tpears = 2' sample2.txt
sed: 1: "sample2.txt": unterminated substitute pattern

我该如何解决这个问题?感谢您的帮助!

[编辑] 我尝试了以下方法,但这些在我的 Mac 上不起作用。

$sed -E '/\[block 1\]|\[blk 2\]/r\\n\\toranges = 3\\n\\tpears = 2' sample2.txt
abc
def

    [block 1]
        apples = 3
        grapes = 4

    [blk 2]
        banana = 2
        apples = 3

$sed -E '/\[block 1\]|\[blk 2\]/r\n\toranges = 3\n\tpears = 2' sample2.txt
abc
def

    [block 1]
        apples = 3
        grapes = 4

    [blk 2]
        banana = 2
        apples = 3

awk 尝试:

$awk -v RS= '/\[block 1\]/{$0 = $0 ORS "\toranges = 3" ORS "\tpears = 2" ORS}
      /\[blk 2\]/{$0 = $0 ORS "\toranges = 5" ORS "\tpears = 2" ORS} 1' sample2.txt
abc
def

    [block 1]
        apples = 3
        grapes = 4

    [blk 2]
        banana = 2
        apples = 3
    oranges = 3
    pears = 2

    oranges = 5
    pears = 2

【问题讨论】:

  • 尝试不就地或提供备份名称。
  • 我仍然收到错误消息。 sed '/[block 1]/a\n\toranges = 3\n\tpeas = 2' sample2.txt sed: 1: "/[block 1]/a\n\torang ...": \ 后面的额外字符在命令的末尾

标签: macos shell sed


【解决方案1】:

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

sed '/^\[\(block 1\|blk 2\)\]\s*$/{n;h;s/\S.*/oranges = 5/p;s//pears = 2/p;x}' file

找到所需的匹配项,将其打印出来,然后将下一行存储在保留空间中。将第一个非空格字符替换为第一个所需的行,重复第二个所需的字符串,然后恢复到原始行。

【讨论】:

    【解决方案2】:

    请注意,提供给a command 的文本必须位于单独的一行:

    sed '/\[block 1\]/ {a\
    \toranges = 3\n\tpears = 2
    }' file
    

    并且所有嵌入的换行符都必须被转义。另一种写法(可能更易读):

    sed '/\[block 1\]/ {a\
        oranges = 3\
        pears = 2
    }' file
    

    另外,当需要插入大量文本(例如多于一行)时,可以考虑使用r command 作为a 命令的替代方法。它将从提供的文本文件中读取数据:

    sed '/\[block 1\]/r /path/to/text' file
    

    要使用一个 sed 程序处理多个部分,您可以使用交替运算符(在 ERE 中可用,注意 -E 标志):

    sed -E '/\[block 1\]|\[blk 2\]/r /path/to/text' file
    

    【讨论】:

    • 或者你可以使用sed '/\[bl\(k\|ock\) [12]\]/ {a\ ...(和4个空格而不是\t
    • 我都试过了,但文件没有更新。 1. sed -E '/[block 1]|[blk 2]/r\\n\\toranges = 3\\n\\tpeas = 2' sample2.txt 2. sed -E '/[block 1]| [blk 2]/r\n\toranges = 3\n\tpears = 2' sample2.txt 我错过了什么吗?
    • @DavidC.Rankin,实际上,BRE 中的(转义)交替运算符 (\|) 是 GNU sed extension。在POSIX 中,只有 ERE 允许交替。
    • @SyncMaster,如果您想要就地更新,请添加 -i 标志。
    • @SyncMaster,或者尝试第一个(或第二个)示例。您可以简单地复制和粘贴它,而无需创建最后两个示例所需的中间文件。
    【解决方案3】:

    这个awk 应该与空的RS 一起使用。这会将每个块分成一条记录。

    awk -v RS= '/\[block 1\]/{$0 = $0 ORS "\toranges = 3" ORS "\tpears = 2" ORS} 
          /\[blk 2\]/{$0 = $0 ORS "\toranges = 5" ORS "\tpears = 2" ORS} 1' file
    
    abc
    def
    [block 1]
        apples = 3
        grapes = 4
        oranges = 3
        pears = 2
    
    [blk 2]
        banana = 2
        apples = 3
        oranges = 5
        pears = 2
    

    【讨论】:

    • 我没有得到预期的输出。新行没有插入 [block 1]。这是我运行它时得到的。 $awk -v RS= '/[块 1]/{$0 = $0 ORS "\toranges = 3" ORS "\tpeas = 2" ORS} > /[blk 2]/{$0 = $0 ORS "\toranges = 5 " ORS "\tpeas = 2" ORS} 1' sample2.txt abc def [block 1] 苹果 = 3 个葡萄 = 4 [blk 2] 香蕉 = 2 个苹果 = 3 个橙子 = 3 个梨 = 2 个橙子 = 5 个梨 = 2
    • 奇怪... OSX 应该使用 '\n' 作为行尾——与 Linux 相同(不像 pre-OSX 使用 '\r' 代替)
    • 我的 Linux 机器上也有同样的问题
    • @SyncMaster:这已经在 OSX awk 上测试过了。 Here is a working demo
    • 还要确保您的输入文件没有 DOS 行结尾(回车)。检查cat -A sample2.txt 命令。如果它在行尾显示^M,则表示需要转换为Unix文件的DOS文件
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-12
    • 1970-01-01
    • 2020-07-07
    • 2016-11-27
    • 1970-01-01
    • 2012-03-24
    • 1970-01-01
    相关资源
    最近更新 更多