5

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

4

3 回答 3

12
sed -e '/\[Block B\]/{:a;n;/^$/!ba;i\inserted line' -e '}'
于 2012-06-25T04:26:40.347 回答
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操作以插入一行文本。Thei后面跟着 a \,因此也插入了前导空格。

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

/^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 表达式可能非常神秘且难以理解——希望我的解释在这方面有所帮助。

于 2013-03-15T17:17:39.473 回答
0

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

sed '/^\[Block B\]/,/^$/!b;/^$/i\inserted line' file
于 2013-09-17T15:03:05.070 回答