Regex 为什么/\w+;:/和/\S+;:/以不同的方式处理回溯?
我分析了这两个正则表达式使用。我认为Regex 为什么/\w+;:/和/\S+;:/以不同的方式处理回溯?,regex,pcre,backtracking,Regex,Pcre,Backtracking,我分析了这两个正则表达式使用。我认为/\S+:/的回溯是正确的。但我不能理解这种区别。我错了吗 虽然这似乎是特定于实现的(RegexBuddy不显示此行为),但可以解释如下: \w无法匹配:,但\S可以。因此,\S+:需要检查输入字符串的更多变体,然后才能确保get无法匹配它 更优化的正则表达式引擎将更快地排除不可能的匹配(例如,当正则表达式包含的文字字符在匹配的当前部分中不存在时),但显然正则表达式101使用的引擎没有这样做。这是一种称为自动占有的优化 发件人: PCRE的“自动占有”优化通常
/\S+:/
的回溯是正确的。但我不能理解这种区别。我错了吗
虽然这似乎是特定于实现的(RegexBuddy不显示此行为),但可以解释如下:
\w
无法匹配:
,但\S
可以。因此,\S+:
需要检查输入字符串的更多变体,然后才能确保get
无法匹配它
更优化的正则表达式引擎将更快地排除不可能的匹配(例如,当正则表达式包含的文字字符在匹配的当前部分中不存在时),但显然正则表达式101使用的引擎没有这样做。这是一种称为自动占有的优化
发件人:
PCRE的“自动占有”优化通常适用于
字符在模式末尾重复(以及在内部)。对于
例如,模式“a\d++
”被编译为“a\d++
”,因为
甚至考虑回溯的可能性都没有意义
输入重复的数字
及
这是一种优化,例如,将a+b
转换为a++b
为了避免返回到永远不会成功的a+
由于:
未包含在\w
中,因此您的模式被解释为\w++:
(第二个++
防止回溯,)。避免了额外的回溯状态,因为没有其他可能匹配的状态
另一方面,:
包含在\S
中,因此此优化不适用于第二种情况
复测
您可以使用(您可以下载Windows版本)查看差异
模式/\w+://
采取11个步骤并输出:
/\w+:/
--->get accept:
+0 ^ \w+
+3 ^ ^ :
+0 ^ \w+
+3 ^ ^ :
+0 ^ \w+
+3 ^^ :
+0 ^ \w+
+0 ^ \w+
+3 ^ ^ :
+4 ^ ^ .*
+6 ^ ^
0: accept:
/(*NO_AUTO_POSSESS)\w+:/
--->get accept:
+18 ^ \w+
+21 ^ ^ :
+21 ^ ^ :
+21 ^^ :
+18 ^ \w+
+21 ^ ^ :
+21 ^^ :
+18 ^ \w+
+21 ^^ :
+18 ^ \w+
+18 ^ \w+
+21 ^ ^ :
+22 ^ ^ .*
+24 ^ ^
0: accept:
但是,如果我们使用控制动词,它将禁用此优化,则模式/(*NO\u AUTO\u have)\w+:/
将执行14个步骤并输出:
/\w+:/
--->get accept:
+0 ^ \w+
+3 ^ ^ :
+0 ^ \w+
+3 ^ ^ :
+0 ^ \w+
+3 ^^ :
+0 ^ \w+
+0 ^ \w+
+3 ^ ^ :
+4 ^ ^ .*
+6 ^ ^
0: accept:
/(*NO_AUTO_POSSESS)\w+:/
--->get accept:
+18 ^ \w+
+21 ^ ^ :
+21 ^ ^ :
+21 ^^ :
+18 ^ \w+
+21 ^ ^ :
+21 ^^ :
+18 ^ \w+
+21 ^^ :
+18 ^ \w+
+18 ^ \w+
+21 ^ ^ :
+22 ^ ^ .*
+24 ^ ^
0: accept:
-它比预期的\S+
少了1步,因为\w+
与:
不匹配
不幸的是,它不支持这个动词
更新:regex101现在支持这个动词,下面是指向要比较的3种情况的链接:
/\S+:/
(14个步骤)-
/\w+:/
(10个步骤)-
/(*无自动拥有)\w+:/
(13个步骤)-
regex101调试器:
我真的很好奇你是如何一步一步地做到这一点的,这样你就可以分析它了@Mehrdad:在regex101.com上,输入一个regex并使用页面左侧的regex调试器
。我很好奇哪个regex引擎更优化,以及是否有任何明显的区别特征(除了您提到的行为)-谢谢!我真的不知道。我非常肯定.NET、Perl和JGSoft的引擎非常聪明,但我不知道是否有比较。无论如何,即使是聪明的引擎,在某些情况下也会陷入灾难性的回溯,尽管它们可能会避免一些给“幼稚”实现带来问题的实例。