为什么我的sed多线查找和替换不能按预期工作?

时间:2017-03-07 01:23:29

标签: sed replace

我有一个简单的 sed 命令,用于替换(包括)//thistest.com----thistest.com之间的所有内容 nothing (删除所有块一起):

sudo sed -i "s@//thistest\.com--.*--thistest\.com@@g" my.file

my.file的内容是:

//thistest.com--
zone "awebsite.com" {
         type master;
         file "some.stuff.com.hosts";
         };

//--thistest.com

由于我使用@作为正则表达式的分隔符,因此我不需要转义/个字符。我也正确地(我认为)逃避了.中的.com。所以我不确切地知道失败的原因。

为什么整个区块都没有被替换?

2 个答案:

答案 0 :(得分:4)

你有两个问题:

  1. Sed不进行多线模式匹配 - 至少不是你期望它的方式。但是,您可以使用多行地址作为替代方案。
  2. 根据您的sed版本,您可能需要转义备用分隔符,尤其是如果您不将它们仅用作替换表达式的一部分。
  3. 因此,以下内容适用于GNU和BSD风格的发布语料库:

    sed '\@^//thistest\.com--@, \@^//--thistest\.com@ d' /tmp/corpus
    

    请注意,在此版本中,我们告诉sed匹配两个模式之间的所有行(包括两个模式)。每个地址模式的开始分隔符都已正确转义。对于删除,该命令也已更改为d而不是替换s,并且为了便于阅读,添加了一些空格。

    我还选择将地址模式锚定到每行的开头。您可能会或可能不会发现对此特定语料库有帮助,但通常明智的做法是,如果可以,并且似乎不会伤害您的用例。

答案 1 :(得分:0)

# separation by line with 1 s//
sed -n -e 'H;${x;s#^\(.\)\(.*\)\1//thistest.com--.*\1//--thistest.com#\2#;p}' YourFile

# separation by line with address pattern
sed -e '\#//thistest.com--#,\#//--thistest.com# d' YourFile

# separation only by char (could be CR, CR/LF, ";" or "oneline") with s//
sed -n -e '1h;1!H;${x;s#//thistest.com--.*\1//--thistest.com##;p}' YourFile

注意:

  • 假设每个文件只有1个 thistest 部分(如果没有,则删除第一个开放到最后一个结束部分之间的任何内容)以使用s //
  • 不适用于使用s //
  • 的大文件(将整个文件加载到内存中)
  • 使用地址模式sed无法在同一行上选择部分,它会搜索第一个模式以启动,并且下一行要停止但在大文件和/或多部分上非常有效