【问题标题】:Precedence rules for matching groups with regexp使用正则表达式匹配组的优先规则
【发布时间】:2012-02-01 15:37:15
【问题描述】:

考虑以下 .NET 正则表达式:

^(REF)?(.{1,10})-(\d{12})-(\d+)$

它定义了四个组,我对它们感兴趣,我将分别分析。

现在,考虑这个正则表达式的输入字符串:

REFmisc03-123456789012-213

可以这样匹配:

(REF)(misc03)-(123456789012)-(213)

而且也可以这样搭配:

()(REFmisc03)-(123456789012)-(213)

是否记录了正则表达式引擎首选的方式,还是随机方式?

【问题讨论】:

  • 我不知道答案,但我敢打赌,随机性是一个因素。为自己构建一个快速测试用例,看看你会得到什么结果。不同的正则表达式引擎可能会以不同的方式解析它,但我希望任何给定引擎都能得到一致的结果。

标签: .net regex operator-precedence capturing-group


【解决方案1】:

这不是随机的。这归结为正则表达式引擎如何解释量词和潜在的回溯。通过量词,我指的是(REF)? 中的?According to MSDN:

通常,量词是贪婪的;它们导致正则表达式 引擎匹配尽可能多的特定模式的出现 可能的。附加 ?量词的字符使它变得懒惰;它 导致正则表达式引擎匹配的出现次数尽可能少 可能。

换句话说,? 是贪婪的,?? 是懒惰的。两者都匹配零次或一次,但它们会影响匹配的执行方式。

关于回溯,MSDN mentions

正则表达式引擎尝试完全匹配可选或 替代子表达式。当它前进到下一种语言时 子表达式中的元素并且匹配不成功,则 正则表达式引擎可以放弃其成功的一部分 匹配并返回到先前保存的状态以进行匹配 正则表达式作为一个整体与输入字符串。这个流程 返回到先前保存的状态以查找匹配项称为 回溯。

另一个有用的资源可以在这里找到更多关于回溯的信息:Possessive Quantifiers

要直接回答您的问题,我们可以比较这两种方法。

贪婪的方法

原始输入: REFmisc03-123456789012-213

使用(REF)? 会将您的文本与 4 个组匹配(不包括整个匹配的第一个组),并且所有组都将成功匹配:

  1. 参考
  2. misc03
  3. 123456789012
  4. 213

这符合您的第一个可能的匹配场景(定义松散):

(REF)(misc03)-(123456789012)-(213)

只要"misc..." 部分的长度为 1-10 个字符,匹配将是相同的,所有 1-10 个字符都出现在第二组中。 REF 部分将始终在第一组中匹配。

新输入: REF-123456789012-213

"misc..." 部分不存在。由于(REF)? 是可选的,而(.{1,10}) 不是,正则表达式引擎将使用"REF" 输入来满足模式的后者(必需)部分并忽略前者(可选)部分。这将产生以下组值:

  1. ""(空字符串,Success 属性 = false
  2. 参考
  3. 123456789012
  4. 213

懒惰的方法

原始输入: REFmisc03-123456789012-213

通过使用(REF)??,并保持模式的其余部分相同,量词变得惰性,这将返回具有这些值的 4 个组:

  1. ""(空字符串,Success 属性 = false
  2. REFmisc03
  3. 123456789012
  4. 213

这符合您的第二个可能的匹配场景:

()(REFmisc03)-(123456789012)-(213)

由于第一组是可选的,带有惰性量词,因此正则表达式引擎可以忽略它。由于 "REFmisc03" 的长度为 9 个字符,因此引擎会将 "REF""misc03" 混为一谈,因为它们适合 (.{1,10}) 组。

新输入: REF-123456789012-213

这与贪婪模式的行为相似,并且适用相同的推理。

另一个新的输入: REFmisc0345-123456789012-213

在此示例中,"misc0345" 部分的长度为 8 个字符。尽管该模式使用了惰性量词,但它无法将 "REFmisc0345" 放入第二组,因为它超过了 10 个字符的限制。正则表达式引擎将回溯并匹配第一组中的"REF",以及第二组中的"misc0345"

  1. 参考
  2. misc0345
  3. 123456789012
  4. 213

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-24
    • 1970-01-01
    • 2012-04-26
    • 1970-01-01
    • 1970-01-01
    • 2011-10-22
    相关资源
    最近更新 更多