Vim正则表达式在字符类中无法匹配空格

7

我正在使用vim执行搜索和替换命令:

%s/lambda\s*{\([\n\s\S]\)*//gc

我试图匹配 { 后的所有单词、结束行和空格字符。例如,这一行的全部内容应该匹配:

    lambda {
  FactoryGirl.create ...

相反,它只匹配换行符之前没有空格的FactoryGirl。我尝试手动替换所有空格,以防有制表符,但都不行。有人能解释一下为什么这样不起作用吗?

2个回答

16

\s是空白字符的原子;\n虽然看起来类似,但在语法上是一个换行符的转义序列。在集合原子[...]中,您不能包含其他原子,只能包含字符(包括一些特殊字符,如\n)。从:help /[]中可以得知:

  • 当未包含“cpoptions”中的“l”标志时,以下转换将被接受 {不适用于Vi}:
\e  <Esc>
\t  <Tab>
\r  <CR>    (NOT end-of-line!)
\b  <BS>
\n  line break, see above |/[\n]|
\d123   decimal number of character
\o40    octal number of character up to 0377
\x20    hexadecimal number of character up to 0xff
\u20AC  hex. number of multibyte character up to 0xffff
\U1234  hex. number of multibyte character up to 0xffffffff

注意:上述提到的其他反斜杠代码不适用于 []!

因此,要么按字面意义指定空格字符[ \t\n...],要么使用相应的字符类表达式[[:space:]...],或者通过逻辑或将原子与集合组合起来\%(\s\|[...]\)


感谢您的详细解释。我不确定为什么之前没有接受,但这个回答彻底解决了这个问题和许多相关问题。 - Eric Hu
这帮助我弄清楚了为什么当我把\s放在括号里时,VIM不能匹配空格。+1 - Zelphir Kaltstahl

1

Vim在[ ... ]字符类中解释字符的方式不同。这并不是字面意义上的,因为该正则表达式无法完全匹配lambda {ssslambda {\\\。至于\s\S的解释...我仍然无法解释。

然而,我几乎可以通过以下方式实现我想要的效果:

%s/lambda\s*{\([\n a-zA-z]\)*//gc

这会忽略标点符号,而我需要它。这样做虽然可行,但很危险:

%s/lambda\s*{\([\n a-zA-z]\|.\)*//gc

因为在最后一个字符后面添加一个字符,比如},会导致vim在全局搜索时卡住。所以我的解决方案是将我需要的标点符号添加到字符类中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接