据我了解,匹配失败时,正则表达式会回溯到之前最接近的选择,选择下一个替代方案并继续匹配。如果没有匹配的可能性,正则表达式是否可以避免回溯?
这是一个场景,我无法向自己解释这个regex101调试器输出。
正则表达式:
^(?<Major>0|[1-9][0-9]*)\.(?<Minor>0|[1-9][0-9]*)\.(?<Patch>0|[1-9][0-9]*)$
输入字符串:
1.222222222222.33333333333.0
当
$
不可能与避免的 [0-9]
匹配时,为什么上面的正则表达式最后会回溯?补丁组用完后,是否会避免回溯Minor和Major的([1-9][0-9]*)
部分?如果是这样,如何以及为什么?
如果有人有更好的例子来展示正则表达式如何决定回溯或不回溯,我们将不胜感激。
这只是一个常识性答案,但据我所知,正则表达式匹配有许多不同的实现和算法。
在这种情况下,在我看来,当算法第一次无法匹配 $ 时,它开始回溯,因为之前的匹配组之一 可能已经 匹配并因此消耗了换行符(因为默认情况下正则表达式匹配是贪婪的,即,每个表达式都会尝试吃掉尽可能多的字符),也许如果使用换行符来匹配 $,则它之前的字符可以匹配表达式的其余部分。
我们人类看到字符串中没有换行符要匹配,并且正则表达式的任何部分都无法匹配,但显然,算法没有注意到这一点。
考虑修改您的正则表达式,以便最后一个匹配组允许换行:
^(?<Major>0|[1-9][0-9]*)\.(?<Minor>0|[1-9][0-9]*)\.(?<Patch>0|[1-9\n][0-9\n]*)$
如果您将其传递到新的正则表达式中:
1.222222222222.33333333
333.0
它会首先尝试将所有 3 放入最后一组。然后它会在最后的 .0 上失败,因为它与 $ 不匹配,因此它可以回溯并将 $ 匹配到 3 之间的换行符,并且第一行将匹配整个正则表达式。哒哒!
您可以在这里看到它的实际效果: https://regex101.com/r/snqyOe/1