使用sed在匹配文本块后插入一行

时间:2012-06-25 04:17:50

标签: bash shell sed awk

我尝试使用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获得所需的结果。谢谢!

3 个答案:

答案 0 :(得分:12)

sed -e '/\[Block B\]/{:a;n;/^$/!ba;i\inserted line' -e '}'

答案 1 :(得分:6)

我在寻找自己问题的解决方案时发现了这个问题,这个问题类似但有点不同。我在这里修改了答案以解决我的问题。

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

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 {开头的行开头,这些行出现在行的开头,并以}结尾也出现在行的开头。选择要处理的块。其余表达式括在{花括号}中,并在所选范围内运行。它包含我们希望插入的每行一个命令,每个命令都带有一个表达式/^}/,该表达式匹配具有结束大括号的行,后跟插入i操作以插入一行文本。 i之后是\,因此也会插入前导空格。

然后我进一步使用了表达式,用一个替换了两个insert命令:

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

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

接下来,我把它减少到一行。它使它变得混乱和难以阅读,但它仍然有效:

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

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

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

我已经写出了这个简写,希望它能解释给那些希望在文本块的末尾插入如何编写sed表达式来实现它的人。 Sed表达式可能非常神秘,难以弄清楚 - 希望我的解释在这方面有所帮助。

答案 2 :(得分:0)

这可能适合你(GNU sed):

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