使用sed替换多行

时间:2012-06-27 19:59:53

标签: sed

我以为我理解了sed,但我猜不是。我有以下两个文件,其中我想用一个不同的行替换“why”和“huh”行。根本没有空格。

  

的test.txt:

hi
why
huh
hi
why
huh
  

的test2.txt:

1
hi
why
huh
hi
why
huh

以下两个命令给出以下结果:

sed "N; s/<why\/>\n<huh\/>/yo/g" test.txt > out.txt

out.txt:
hi
why
huh
hi
yo

sed "N; s/<why\/>\n<huh\/>/yo/g" test2.txt > out2.txt

out2.txt:
1
hi
yo
hi
why
huh

我对sed不了解什么?为什么两个输出文件都不包含以下内容:

hi
yo
hi
yo

3 个答案:

答案 0 :(得分:8)

你的表达几乎是正确的,但它有两个问题:

  • 如果您想将why作为单词匹配,则应将\<\>放在其周围。你确实在它周围放了<\/>。所以,第一次修正是:

    $ sed 'N; s/\<why\>\n\<huh\>/yo/g' test.txt
    
  • 但它也不起作用:

    $ sed 'N; s/\<why\>\n\<huh\>/yo/g' test.txt
    hi
    why
    huh
    hi
    yo
    

    为什么它只替换第二对线?好吧,在第一行中,N命令会将why连接到hi,并在pattern space中保留字符串hi\nwhy。此字符串与s///命令不匹配,因此只打印该行。下一次,您在模式空间中拥有字符串huh并将hi连接到它。在下一行中,您将在要替换的模式空间中使用why\nhuh

    解决方案是仅在当前行为why时使用address /^why$/连接下一行:

    $ sed '/^why$/ {N; s/\<why\>\n\<huh\>/yo/g}' test.txt
    hi
    yo
    hi
    yo
    

答案 1 :(得分:3)

brandizzi的答案中,美妙地解释了它没有取代两对线的原因。

然而,如果我们更进一步。假设我们有以下文件,我们想用“pure \ nmilk”替换“apple \ njuice”。

  

的test.txt

water water water water 
water water water apple
juice water water apple
juice water water water

模式过滤方式不起作用。

sed '/apple/ {N; s/apple\njuice/pure\nmilk/g}' test.txt 

water water water water
water water water pure
milk water water apple
juice water water water

因为来自test.txt的第二个苹果已经被N连接到前一行,所以没有被模式过滤器捕获。

我能想到的一个解决方案是使用分支连接所有行然后进行替换。

sed ':a;N;$!ba;s/apple\njuice/pure\nmilk/g' test.txt 

water water water water
water water water pure
milk water water pure
milk water water water

看起来很愚蠢,但我还没有想到更好的方法。

答案 2 :(得分:1)

这适用于test.txt文件:

sed '/hi/! { N ; s/why\nhuh/yo/ }' test.txt

这意味着:

如果未在一行中找到hi(它将是why),请阅读下一个并用yo替换所有内容。否则直接打印(hi时)。

输出:

hi
yo
hi
yo