Sed正则表达式和子串否定

时间:2012-01-29 12:17:31

标签: regex sed

查找子字符串(前面跟着特定字符串的字符串)的正确语法是什么?匹配特定模式?

例如,我想将所有开始的子字符串与BEGIN_ end _END一起使用,其间的子字符串为等于FOO;并用格式“( inner substring )”替换整个子字符串。以下内容将匹配:

  • BEGIN_bar_END - > (bar)
  • BEGIN_buz_END - > (buz)
  • BEGIN_ihfd8f398IHFf9f39_END - > (ihfd8f398IHFf9f39)

BEGIN_FOO_END不匹配。

我玩过以下内容,但似乎无法找到正确的语法:

sed -e 's/BEGIN_(^FOO)_END/($1)/g'
sed -e 's/BEGIN_([^FOO])_END/($1)/g'
sed -e 's/BEGIN_(?!FOO)_END/($1)/g'
sed -e 's/BEGIN_(!FOO)_END/($1)/g'
sed -e 's/BEGIN_(FOO)!_END/($1)/g'
sed -e 's/BEGIN_!(FOO)_END/($1)/g'

4 个答案:

答案 0 :(得分:35)

sed,IIRC中没有一般否定运算符,因为对DFAs否定的正则表达式的编译需要指数时间。您可以使用

解决此问题
'/BEGIN_FOO_END/b; s/BEGIN_\(.*\)_END/(\1)/g'

其中/BEGIN_FOO_END/b表示:如果我们找到BEGIN_FOO_END,则分支(跳转)到sed脚本的末尾。

答案 1 :(得分:15)

这个主题可能很旧,但为了完整起见,否定运算符!

让所有不快乐变得非常快乐:

echo -e 'happy\nhappy\nunhappy\nhappy' | sed '/^happy/! s/.*/VERY HAPPY/'

在此处找到:How to globally replace strings in lines NOT starting with a certain pattern

答案 2 :(得分:4)

这可能对您有用:

sed 'h;s/BEGIN_\(.*\)_END/(\1)/;/^(FOO)$/g' file

仅当每行只有一个字符串时才有效。

每行多个字符串:

sed 's/BEGIN_\([^F][^_]*\|F[^O][^_]*\|FO[^O][^_]*\|FOO[^_]\+\)_END/\(\1\)/g' file

或者更容易理解:

sed 's/\(BEGIN_\)FOO\(_END\)/\1\n\2/g;s/BEGIN_\([^\n_]*\)_END/(\1\)/g;s/\n/FOO/g' file

答案 3 :(得分:2)

我不知道一个漂亮的方式,但你总能做到这一点:

$ cat file
BEGIN_FOO_END
BEGIN_FrOO_END
BEGIN_rFOO_END
$ sed '/BEGIN_FOO_END/ !{s/BEGIN_\([^_]*\)_END/(\1)/}' file 
BEGIN_FOO_END
(FrOO)
(rFOO)