如何找到一个模式,然后是第二个模式,然后仅在第二个模式后使用sed附加文本?

时间:2014-02-01 22:50:32

标签: bash shell sed

我正在尝试在文件中找到一个模式,然后找到第二个模式,然后在第二个模式之后添加一个带有文本的行。

例如,如果这是我正在尝试更改的文件中的文本:

aaa
bbb
ccc
ddd
eee
fff
ggg      

我想匹配“aaa”然后“ddd”,然后在“ddd”之后添加“hello”到该行。

我试过

sed -i "/aaa/,/ddd/a\hello" foo.txt

但我最终得到的是:

aaa
hello
bbb
hello
ccc
hello
ddd
hello
eee
fff
ggg

编辑:另外,有没有办法确保这只发生一次,或者只在第一次出现第二种模式之后(示例中为“ddd”)?

2 个答案:

答案 0 :(得分:2)

sed $'/aaa/,/ddd/ { /ddd/ a\hello\n }' patterns

大括号中的命令在匹配ddd的任何行之后添加行hello。但是,大括号中的命令仅适用于aaa和ddd之间的行。

或者,使用替代而不是添加:

sed '/aaa/,/ddd/ s/ddd/ddd\nhello/' patterns

这会产生:

aaa
bbb
ccc
ddd
hello
eee
fff
ggg    

此版本的作用是限制替代品仅在aaa行发生后才发生。

备选方案:假设我们只想在第一次出现ddd后添加hello,并且只有在事先发生aaa时才添加。在那种情况下:

sed $'0,/ddd/ {/aaa/,/ddd/ { /ddd/ a\hello\n}}' patterns

第一个范围说明符0,/ddd/将所有后续范围限制为直到第一次出现的ddd的行。该命令的其余部分与以前一样。

答案 1 :(得分:2)

这可能适合你(GNU sed):

sed '/aaa/,/ddd/!b;/ddd/a\hello' file

编辑:

如果您希望它只在文件中出现一次:

sed 'x;/./{x;b};x;/aaa/,/ddd/!b;/ddd/!b;h;a\hello' file

请参阅John1024解决方案,以优雅地使用Bash和Sed。

N.B。如果可能的话,我会删除这个答案但是SO不允许删除已接受的答案。