【问题标题】:Why does `[a-zA-Z]*` not match a word with leading whitespace?为什么 `[a-zA-Z]*` 不匹配带有前导空格的单词?
【发布时间】:2016-06-16 14:32:57
【问题描述】:

给定这样的字符串:

    aWordToRemove;

把它变成这样:

    TEST;

如果我运行命令 :s/[a-zA-Z]*/TEST/ 那么它什么都不匹配。

但是,如果我运行:s/[a-zA-Z]\w*/TEST/,那么它将用TEST 替换aWordToRemove,并保持前导空格和尾随分号不变。

如果第一个正则表达式有前导空格,为什么它找不到单词?

为什么将\w 放在* 之前会起作用?

编辑:

Vim 似乎很挑剔。以下是一些有效和无效的正则表达式。

工作正则表达式

s/[a-zA-Z]\w*/TEST/

s/[a-zA-Z][a-zA-Z]*/TEST/

s/[a-zA-Z]\+/TEST/

不工作的正则表达式

s/[a-zA-Z]*/TEST/

s/[a-zA-Z]+/TEST/

【问题讨论】:

  • 因为你需要一个全局修饰符。或者更好的是 + 而不是 *。否则,模式在开始时匹配。
  • 你需要的模式是s/[a-zA-Z]\+/TEST/
  • 你知道为什么需要反斜杠吗?
  • 这只是spec 的一部分。创作者显然认为+ 应该是字符,\+ 应该是量词。

标签: regex vim


【解决方案1】:

因为它在行开始和第一个空格之间找到空字符串,并用空字符串替换它,然后停止。

你可以试试:s/[a-zA-Z]*//g,它会在第一次替换后继续尝试。

Kleene 闭合 (*) 无法匹配任何内容。一个类似的表达式,就像你的一样,是:s/[a-zA-Z][a-zA-Z]*//,它保证至少匹配一个字母,防止它在匹配第一个空字符串时停止。事实上,这很常见,以至于运算符a+ 是大多数正则表达式方言中aa* 的简写。

这就是 :s/[a-zA-Z]\w*// 起作用的原因,因为它必须至少匹配一个字母才能消耗更多。

【讨论】:

  • 或者把*改成+
  • :s/[a-zA-Z][a-zA-Z]*// == :s/[a-zA-Z]+//
  • 在 vim 中,您需要在 + 之前添加一个反斜杠。 Vim 就是这样有趣。
  • @ncphillips:不同的正则表达式方言不同。正则表达式只定义了四种操作:优先级(通常是())、Kleene 闭包(通常是*)、联合(通常是|)和连接(通常只是字符)。所有其他操作都是这些操作的扩展,因此不同的软件执行方式不同。
  • @Meninx:这是你所期望的吗?你对这种行为有疑问吗?发生这种情况的原因是因为a* 可以匹配长度为零的字符串,对于a 的任何值(在您的情况下为a=[^a-z])。字符串word 中的每个字符之间以及字符串本身的前后都有一个长度为零的字符串。
【解决方案2】:

要学习vimregex,首先要学习magicvery magicno magic:h magic查看详情。

Vim 将magic 设置为默认值。 magic 是 BRE -like,这意味着您必须转义一些字符以赋予它们特殊含义,否则它们只是文字字符。 like ( ) | + ... 说到这一点,就和BRE一样。

如果你想让正则表达式 ERE 或 PCRE -like,你可以在你的模式前加上一个\v,这样::s/\v[...]+/whatever/g 就可以了。在这种very magic 模式下,您必须转义那些具有特殊含义的字符才能获得字面值。

我建议你阅读 vim magic 文档,有一个表格,可以比较不同的魔法模式。你可以做一些测试。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-22
    相关资源
    最近更新 更多