【问题标题】:use sed to insert a line after matching a block of text在匹配文本块后使用 sed 插入一行
【发布时间】:2012-06-25 04:17:50
【问题描述】:

我尝试使用 sed 在以下文件中 [Block B] 之后插入一行:

[Block A]  
line 1  
line 2  

[Block B]  
line 1  
line 2  

[Block C]  
line 1  
line 2  

我使用的命令:

sed '/\[Block B\]/,/^$/a\inserted line' file

正确/期望的结果应该是:

[Block B]  
line 1  
line 2  
inserted line  

但是,我得到了这个:

[Block B]  
inserted line  
line 1  
inserted line  
line 2  
inserted line  

请告诉我如何使用 sed 获得所需的结果。谢谢!

【问题讨论】:

    标签: bash shell sed awk


    【解决方案1】:
    sed -e '/\[Block B\]/{:a;n;/^$/!ba;i\inserted line' -e '}'
    

    【讨论】:

    • 非常感谢!这真的很有帮助。但是,我真的不明白为什么这会奏效,哈哈!我想是时候阅读 sed 了
    • 你能解释一下为什么你需要额外的 -e 来使命令工作。由于某些奇怪的原因,以下命令不起作用: sed -e '/[Block B]/{:a;n;/^$/!ba;i\inserted line}' file
    • @tonytz 你可能会喜欢这些sed one-liners
    • @tonytz: 额外的-eia 等命令知道插入或附加字符串的结束位置。
    • 对于任何有兴趣的人来说,这里有另一个同样有效的命令: sed -e '/[Block B]/,/^$/{/^$/!b;i\inserted line' - e '}' 文件
    【解决方案2】:

    我在为自己的问题寻找解决方案时发现了这个问题,这与我的问题相似但略有不同。我调整了这里的答案来解决我的问题。

    我需要在配置文件中的块末尾插入一些文本,如下所示:

    name1 {
        ...
    }
    
    name2 {
        ...
        inserted text line 1
        inserted text line 2
    }
    
    name3 {
        ....
    }
    

    为了实现这一点,我从上面获取了@toyntz 评论并对其进行了调整:

    /^name2 {/,/^}/{
        /^}/i\    inserted text line 1
        /^}/i\    inserted text line 2
    }
    

    这只是 sed 表达式;它可以放在一个文件中并使用sed -f 执行,如下所示:

    $ sed -f sed_expression data_file
    

    第一个表达式搜索以name2 { 开始出现在行首并以} 结束也出现在行首的行范围。这选择了要处理的块。其余表达式包含在{curly 大括号} 中,并在所选范围内进行操作。它包含我们希望插入的每一行命令,每个命令都有一个表达式/^}/,它与带有右花括号的行匹配,然后是插入i 操作以插入一行文本。 i 后跟 \ 以便同时插入前导空格。

    然后我将表达式更进一步,将两个插入命令替换为一个:

    /^name2 {/,/^}/{
        /^}/i\
        inserted text line 1\
        inserted text line 2
    }
    

    在这里,一个命令要插入的文本分布在以下两行中。请注意第一行附加的尾随 \ 以继续单个命令。

    接下来,我将其缩减为一行。它使它变得凌乱且难以阅读,但它仍然有效:

    /^name2 {/,/^}/{/^}/i\    inserted text line 1\n    inserted text line 2
    }
    

    要插入的两行由换行符\n 分隔。精明的读者会注意到实际上有两行——你不能把右大括号放在第一行的末尾;这就是为什么上面的其他答案有第二个 -e 表达式。所以,以上是我能做的最好的。在 bash 命令行上表示:

    sed -e '/^name2 {/,/^}/{/^}/i\    inserted text line 1\n    inserted text line 2' -e '}' data_file
    

    我写了这个速记,希望它能向任何希望在文本块末尾插入的人解释如何编写 sed 表达式来实现这一点。 sed 表达式可能非常神秘且难以理解 - 希望我的解释在这方面有所帮助。

    【讨论】:

      【解决方案3】:

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

      sed '/^\[Block B\]/,/^$/!b;/^$/i\inserted line' file
      

      【讨论】:

        猜你喜欢
        • 2013-03-11
        • 2018-11-24
        • 2016-09-29
        • 1970-01-01
        • 2013-07-02
        • 2020-01-14
        • 1970-01-01
        相关资源
        最近更新 更多