匹配具有正则表达式的组的优先规则

时间:2012-02-01 15:37:16

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

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

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

它定义了四组,我感兴趣,我将分别进行分析。

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

REFmisc03-123456789012-213

可以像这样匹配:

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

也可以这样匹配:

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

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

1 个答案:

答案 0 :(得分:2)

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

  

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

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

关于回溯,MSDN mentions

  

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

可以在此处找到了解有关回溯的更多有用资源:Possessive Quantifiers

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

贪婪的方法

原始输入: REFmisc03-123456789012-213

(REF)?的使用情况会使您的文字与4组相匹配(第一组不包括整个匹配),所有组都会成功匹配:

  1. REF
  2. misc03
  3. 123456789012
  4. 213
  5. 这符合您的第一个可能的匹配方案(松散定义):

      

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

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

    新输入: REF-123456789012-213

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

    1. ""(空字符串,Success property = false
    2. REF
    3. 123456789012
    4. 213
    5. 懒惰的方法

      原始输入: REFmisc03-123456789012-213

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

      1. ""(空字符串,Success property = false
      2. REFmisc03
      3. 123456789012
      4. 213
      5. 这符合您的第二种可能的匹配方案:

          

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

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

        新输入: REF-123456789012-213

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

        另一项新输入: REFmisc0345-123456789012-213

        在此示例中,"misc0345"部分长度为8个字符。虽然模式使用惰性量词,但它不能使"REFmisc0345"适合第二组,因为它超过了10个字符的限制。正则表达式引擎将回溯并匹配第一组中的"REF"和第二组中的"misc0345"

        1. REF
        2. misc0345
        3. 123456789012
        4. 213