查找子字符串(前面跟着特定字符串的字符串)的正确语法是什么?不匹配特定模式?
例如,我想将所有开始的子字符串与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'
答案 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)