正则表达式 PHP。减少步骤:受固定宽度 Lookbehind 限制

2024-04-09

我有一个正则表达式将用于匹配@users 标签。

我使用 lokarround 断言,让标点符号和空白字符包围标签。
还有一个额外的复杂性,有一种代表 html 的 bbcode。
我有两种类型的 bbcode,内联(^B bold ^b)和块(^C center ^c).
必须传递内联字符才能到达上一个或下一个字符。 并且这些块可以包围标签,就像标点符号一样。

我做了一个有效的正则表达式。我现在想做的是减少每个不匹配的角色所执行的步骤数。
起初我以为我可以做一个正则表达式来查找@,当找到时,它会开始查看lookarrounds,这在没有内联bbcodes的情况下也有效,但由于lookbehind无法量化,所以更困难,因为我无法添加((\^[BIUbiu])++)*在里面,产生更多的步骤。

如何以更少的步骤更高效地执行正则表达式?

这是它的简化版本,在 Regex101 链接中有完整的正则表达式。

(?<=[,\.:=\^ ]|\^[CJLcjl])((\^[BIUbiu])++)*@([A-Za-z0-9\-_]{2,25})((\^[BIUbiu])++)*(?=[,\.:=\^ ]|\^[CJLcjl])

https://regex101.com/r/lTPUOf/4/ https://regex101.com/r/lTPUOf/4/


经验法则:

如果出现以下情况,不要让引擎尝试匹配每个字符 有一些界限。

引用最初来自这个答案。由于最外层交替的左侧,遵循正则表达式可以显着减少步骤,从 ~20000 到 ~900:

(?:[^@^]++|[@^]{2,}+)(*SKIP)(*F)
|
(?<=([HUGE-CHARACTER-CLASS])|\^[cjleqrd])
    (\^[34biu78])*+@([a-z\d][\w-.]{0,25}[a-z\d])(\^[34biu78])*+(?=(?1))

实际上,我不太关心 regex101 报告的步骤数,因为在您自己的环境中这不是真的,并且某些步骤是否真实或遗漏了哪些步骤并不明显。但在这种情况下,由于正则表达式的逻辑很清晰,并且差异很大,所以这是有道理的。

逻辑是什么?

我们首先尝试匹配可能根本不需要的东西,将其扔掉并寻找可能与我们的模式匹配的部分。[^@^]++匹配到一个@ or ^符号(所需字符)和[@^]{2,}+防止引擎在发现它毫无进展之前采取额外的步骤。所以我们要尽快让它失败。

您可以使用iflag 而不是定义字母的大写形式(但这可能会产生一点影响)。

See 现场演示在这里 https://regex101.com/r/lTPUOf/17

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

正则表达式 PHP。减少步骤:受固定宽度 Lookbehind 限制 的相关文章

随机推荐