考虑以下.NET正则表达式:
^(REF)?(.{1,10})-(\d{12})-(\d+)$
它定义了四组,我感兴趣,我将分别进行分析。
现在,考虑一下这个正则表达式的输入字符串:
REFmisc03-123456789012-213
可以像这样匹配:
(REF)(misc03)-(123456789012)-(213)
也可以这样匹配:
()(REFmisc03)-(123456789012)-(213)
是否记录了正则表达式引擎首选的方式,还是随机的?
答案 0 :(得分:2)
这不是随意的。这可以归结为正则表达式引擎如何解释量词以及潜在的回溯。通过量词,我指的是?
中的(REF)?
。 According to MSDN:
通常,量词是贪婪的;它们会导致正则表达式 引擎匹配尽可能多的特定模式 可能。附加?量词的字符使它变得懒惰;它 使正则表达式引擎匹配尽可能少的事件 可能的。
换句话说,?
是贪婪的,??
是懒惰的。两者都匹配零次或一次,但它们会对匹配的执行方式产生影响。
关于回溯,MSDN mentions:
正则表达式引擎尝试完全匹配可选项或 替代子表达式。当它进入下一个语言 子表达式中的元素和匹配不成功, 正则表达式引擎可以放弃其成功的一部分 为了匹配,匹配并返回先前保存的状态 使用输入字符串作为整体的正则表达式。这个流程 返回到先前保存的状态以查找匹配称为 回溯。
可以在此处找到了解有关回溯的更多有用资源:Possessive Quantifiers。
要直接回答您的问题,我们可以比较两种方法。
原始输入: REFmisc03-123456789012-213
(REF)?
的使用情况会使您的文字与4组相匹配(第一组不包括整个匹配),所有组都会成功匹配:
这符合您的第一个可能的匹配方案(松散定义):
(REF)(misc03) - (123456789012) - (213)
只要"misc..."
部分长度为1-10个字符,匹配就会相同,第二组中出现所有1-10个字符。 REF
部分将始终在第一组中匹配。
新输入: REF-123456789012-213
"misc..."
部分缺席。由于(REF)?
是可选的,而(.{1,10})
不是,因此正则表达式引擎将使用"REF"
输入来满足模式的后一个(必需)部分并忽略前一个(可选)部分。这将产生以下组值:
""
(空字符串,Success
property = false
) 原始输入: REFmisc03-123456789012-213
通过使用(REF)??
,并保持模式的其余部分相同,量词变得懒惰,并返回4个具有这些值的组:
""
(空字符串,Success
property = false
)这符合您的第二种可能的匹配方案:
()(REFmisc03) - (123456789012) - (213)
由于第一组是可选的,具有延迟量词,因此正则表达式引擎可以忽略它。由于"REFmisc03"
长度为9个字符,因此引擎会"REF"
进入"misc03"
,因为它们适合(.{1,10})
组。
新输入: REF-123456789012-213
这与贪婪模式的行为类似,并且适用相同的推理。
另一项新输入: REFmisc0345-123456789012-213
在此示例中,"misc0345"
部分长度为8个字符。虽然模式使用惰性量词,但它不能使"REFmisc0345"
适合第二组,因为它超过了10个字符的限制。正则表达式引擎将回溯并匹配第一组中的"REF"
和第二组中的"misc0345"
: