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

时间:2019-01-07 12:34:39

标签: php regex regex-lookarounds lookbehind

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

我使用lokarround断言,让标点符号和空格字符包围标签。
这增加了复杂性,有一种表示html的bbcode。
我有两种类型的bbcode,内联(^B粗体^b)和块(^C中心^c)。
内联字符必须直通以到达上一个或下一个字符。 就像标点符号一样,这些块也被允许围绕标签。

我做了一个有效的正则表达式。我现在想做的是减少它不会匹配的每个角色的步数。
起初我以为我可以做一个正则表达式,只寻找@,当它找到时,它会开始寻找lookarrounds,这种方法不需要内联bbcode,但是由于lookbehind无法量化,因此自我无法在其中添加((\^[BIUbiu])++)*,从而产生了更多步骤。

如何以更少的步骤使我的正则表达式更有效?

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

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

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

1 个答案:

答案 0 :(得分:1)

经验法则

  

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

引用最初来自此答案。遵循正则表达式会因为最外侧交替的左侧(从〜20000到〜900)而极大地减少了步长:

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

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

逻辑是什么?

我们首先尝试匹配可能根本不需要的内容,将其扔掉,然后寻找可能与我们的模式匹配的部分。 [^@^]++最多可匹配@^符号(所需字符),而[@^]{2,}+可防止引擎在发现错误之前采取额外的措施。因此,我们使其尽快失效。

您可以使用i标志代替定义大写字母形式的字母(但是可能会产生一些影响)。

请参见live demo here