正则表达式:PCRE原子团不起作用

时间:2018-08-25 18:32:11

标签: regex pcre

在PCRE正则表达式中,我使用了原子组来减少回溯。

<\/?\s*\b(?>a(?:bbr|cronym|ddress|pplet|r(?:ea|ticle)|side|udio)?|b(?:ase|asefont|d[io]|ig|lockquote|ody|r|utton)?|c(?:anvas|aption|enter|ite|ode|ol(?:group)?)|d(?:ata(?:list)?|[dlt]|el|etails|fn|ialog|i[rv])|em(?:bed)?|f(?:i(?:eldset|g(?:caption|ure))|o(?:nt|oter|rm)|rame(?:set)?)|h(?:[1-6r]|ead(?:er)?|tml)|i(?:frame|mg|nput|ns)?|kbd|l(?:abel|egend|i(?:nk)?)|m(?:a(?:in|p|rk)|et(?:a|er))|n(?:av|o(?:frames|script))|o(?:bject|l|pt(?:group|ion)|utput)|p(?:aram|icture|re|rogress)?|q|r[pt]|ruby|s|s(?:amp|ection|elect|mall|ource|pan|trike|trong|tyle|ub|ummary|up|vg)|t(?:able|body|[dhrt]|emplate|extarea|foot|head|ime|itle|rack)|ul?|v(?:ar|ideo)|wbr)\b

REGEX101

但是在示例调试中,我看到在f检查结束之后,其他选项更进一步了。我试图在f检查失败后停止它,以便它不检查其余表达式。怎么了?

2 个答案:

答案 0 :(得分:2)

我将假定您知道在这里使用正则表达式正在做什么,因为可能有人认为PCRE不是以类似于“树”的方式实现这种匹配的最佳方法。但是我对此并不感到困惑。

使用条件语句的想法不错,但是它以条件本身的形式添加了额外的步骤。另外,每个条件只能在两个方向上分支。

PCRE具有一项称为“回溯控制动词”的功能,可让您精确地执行所需的操作。他们有不同的控制级别,在这种情况下,我建议的控制级别是最强的:

<\/?\s*\b(?>a(?:bbr|cronym|ddress|pplet|r(?:ea|ticle)|side|udio)?|b(?:ase|asefont|d[io]|ig|lockquote|ody|r|utton)?|c(?:anvas|aption|enter|ite|ode|ol(?:group)?)|d(?:ata(?:list)?|[dlt]|el|etails|fn|ialog|i[rv])|em(?:bed)?|f(*COMMIT)(?:i(?:eldset|g(?:caption|ure))|o(?:nt|oter|rm)|rame(?:set)?)|h(?:[1-6r]|ead(?:er)?|tml)|i(?:frame|mg|nput|ns)?|kbd|l(?:abel|egend|i(?:nk)?)|m(?:a(?:in|p|rk)|et(?:a|er))|n(?:av|o(?:frames|script))|o(?:bject|l|pt(?:group|ion)|utput)|p(?:aram|icture|re|rogress)?|q|r[pt]|ruby|s|s(?:amp|ection|elect|mall|ource|pan|trike|trong|tyle|ub|ummary|up|vg)|t(?:able|body|[dhrt]|emplate|extarea|foot|head|ime|itle|rack)|ul?|v(?:ar|ideo)|wbr)\b

https://regex101.com/r/p572K8/2

只需在'f'分支之后添加单个(*COMMIT)动词,就可以将在这种情况下查找失败所需的步骤数减少了一半。

(*COMMIT)告诉引擎在那时进行匹配。如果找不到匹配项,它甚至不会再次尝试从</开始的匹配项。

要完全优化表达式,必须在分支发生后的每个点添加(*COMMIT)

您可以做的另一件事是,尝试对替代方案进行重新排序,以便对最常见的替代方案进行优先排序。在您的优化过程中,可能还需要考虑其他因素。

答案 1 :(得分:0)

因为这是原子团的工作方式。这个想法是:

  

在当前位置处,找到与原子分组内的模式匹配匹配的第一个序列,并坚持下去。   (来源:Confusion with Atomic Grouping - how it differs from the Grouping in regular expression of Ruby?

因此,如果原子组内没有匹配项,它将遍历所有选项。 您可以改用条件句:

  

Regex101