我使用regex101分析了这两个正则表达式。我认为/\S+:/
的回溯是正确的。但我无法理解这种差异。我错了吗?
答案 0 :(得分:15)
这是名为auto-possessification
的{{3}}优化。
来自pcre:
PCRE"自动拥有"优化通常适用于 字符在模式的末尾(以及内部)重复。对于 例如,模式"
a\d+
"编译好像是"a\d++
"因为 即使考虑回溯的可能性也没有意义 重复数字。
和
这是一项优化,例如,将
a+b
转换为a++b
为了避免回溯到永远无法成功的a+
。
由于:
中未包含\w
,因此您的模式被解释为\w++:
(第二个+
会阻止回溯,http://pcre.org/pcre.txt)。避免了额外的回溯状态,因为它没有可能匹配的另一个状态。
另一方面,:
中包含\S
,因此此优化不适用于第二种情况。
您可以使用see possessive quantifiers(您可以下载pcretest
的Windows版本)查看差异。
模式/\w+:/
需要 11步并输出:
/\w+:/
--->get accept:
+0 ^ \w+
+3 ^ ^ :
+0 ^ \w+
+3 ^ ^ :
+0 ^ \w+
+3 ^^ :
+0 ^ \w+
+0 ^ \w+
+3 ^ ^ :
+4 ^ ^ .*
+6 ^ ^
0: accept:
但是,如果我们使用控制动词 here 来禁用此优化,则模式/(*NO_AUTO_POSSESS)\w+:/
需要 14步并输出:< / p>
/(*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+
与:
不匹配。
不幸的是 (*NO_AUTO_POSSESS)
不支持此动词。
更新: regex101现在支持此动词,这里有3个要比较的案例的链接:
/\S+:/
(14个步骤) - regex101
/\w+:/
(10个步骤) - https://regex101.com/r/cw7hGh/1/debugger
/(*NO_AUTO_POSSESS)\w+:/
(13个步骤) - https://regex101.com/r/cw7hGh/2/debugger
regex101调试器:
答案 1 :(得分:11)
虽然这似乎是特定于实现的(RegexBuddy没有显示此行为),但可以解释如下:
\w
无法匹配:
,但\S
可以。因此,\S+:
需要检查输入字符串的更多变体,然后才能确保get
无法与之匹配。
更优化的正则表达式引擎将更快地排除不可能的匹配(例如,当正则表达式包含匹配的当前部分中不存在的文字字符时),但显然regex101正在使用的引擎不这样做。