【问题标题】:Regex lazy vs greedy confusion正则表达式懒惰与贪婪的混淆
【发布时间】:2014-04-19 22:07:17
【问题描述】:

我对正则表达式和贪婪与懒惰有点困惑。这真的很简单,感觉就像我错过了一些明显的东西。

我已经尽可能地简化了我的问题以使其清楚。考虑以下字符串和正则表达式模式。

string:
aaxxxb

pattern:
(?<=a)(.*?)(?=b)

result:
axxx

what I expected:
xxx

这个结果是我使用 .* 而不是 .* 所期望的结果?我错过了什么?

显然,如果我使用 a.*?b 也会得到 aaxxxb。为什么是这样?不应该惰性(如 .*?)返回尽可能少的字符吗?

【问题讨论】:

标签: regex


【解决方案1】:

您错过了这样一个事实,即正则表达式引擎从左到右逐个位置工作,并且一旦在当前位置找到匹配项就会成功。

在您的示例中,模式成功的第一个位置是第二个“a”。

懒惰只在右侧起作用。

如果要获取“xxx”,更好的方法是使用取反字符类[^ab]*而不是.*?

注意:与主题不完全相关,但很高兴知道:DFA 正则表达式引擎将尝试在交替的情况下获得最大的结果,而 NFA 会为您提供第一个成功的结果。

【讨论】:

  • 总是很高兴阅读你。正如您所说,掌握“正则表达式引擎从左到右,逐个位置工作”是一个常见的绊脚石......而且更大的困惑来源是我们正在从左到右工作both 在字符串和模式上。当我们谈到从左到右时,我希望有一种方法可以轻松表达。顺便说一句,我知道你知道这一点,但 .NET 有一个从右到左的选项! :)
  • @zw81:谢谢!事实上,不要忘记世界上的一部分是从右到左读写的,而 .NET 为正则表达式提供了这种可能性。
【解决方案2】:

user1277327,您的模式中的(?&lt;=a) 部分表示“前面有一个'a'”。当正则表达式引擎在您的字符串 aaxxxb 上启动时,第一个“a”不满足后面的断言,但第二个“a”可以。很好,但是引擎可以匹配那个“a”吗?是的,.* 中的点允许引擎匹配这个“a”。懒惰的修饰符?告诉点星只吃必要的字符,直到我们能够匹配接下来的内容。接下来是先行断言下一个字符是“b”。所以引擎吃掉了三个 x 字符。总匹配是 axxx。

如果您对贪婪/懒惰感到困惑,您可能想看看the levels of regex greedlookarounds 附带的 tut 也可能有所帮助。

【讨论】:

    猜你喜欢
    • 2012-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    • 1970-01-01
    相关资源
    最近更新 更多