2012-06-27 173 views
3

我以为我理解sed,但我猜不是。我有以下两个文件,其中我想用一个不同的行替换“为什么”和“呵”行。根本没有空白。使用sed替换多行

的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有什么不了解?为什么不两个输出文件包含以下内容:

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

这意味着:

当一行中没有发现hi(这将是

hi 
yo 
hi 
yo 

回答

7

你的表情几乎是正确的,但它有两个问题:如果你想匹配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命令将连接whyhi,在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 
    
+0

谢谢,这正是我想要的 - 匹配几个连续的行,因为第一个找到。 – user1145925

1

这应该test.txt文件工作why),读下一个并用yo代替它。否则直接打印(当hi)。

输出:

hi 
yo 
hi 
yo 
2

为什么没有更换两对线的原因是精美的解释在brandizzi的答案中。

但是,如果我们采取了一步。假设我们有以下的文件,我们要替换“苹果\ njuice”与“纯\ nmilk”。

的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 

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

+0

第二个会比较好,因为它不会有遗漏取代的任意惊喜。 –