正则表达式如何决定何时回溯?

问题描述 投票:0回答:1

据我了解,匹配失败时,正则表达式会回溯到之前最接近的选择,选择下一个替代方案并继续匹配。如果没有匹配的可能性,正则表达式是否可以避免回溯?

这是一个场景,我无法向自己解释这个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]*)
部分?如果是这样,如何以及为什么?

如果有人有更好的例子来展示正则表达式如何决定回溯或不回溯,我们将不胜感激。

regex
1个回答
0
投票

这只是一个常识性答案,但据我所知,正则表达式匹配有许多不同的实现和算法。

在这种情况下,在我看来,当算法第一次无法匹配 $ 时,它开始回溯,因为之前的匹配组之一 可能已经 匹配并因此消耗了换行符(因为默认情况下正则表达式匹配是贪婪的,即,每个表达式都会尝试吃掉尽可能多的字符),也许如果使用换行符来匹配 $,则它之前的字符可以匹配表达式的其余部分。

我们人类看到字符串中没有换行符要匹配,并且正则表达式的任何部分都无法匹配,但显然,算法没有注意到这一点。

考虑修改您的正则表达式,以便最后一个匹配组允许换行:

^(?<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

© www.soinside.com 2019 - 2024. All rights reserved.