在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
但是在示例调试中,我看到在f
检查结束之后,其他选项更进一步了。我试图在f
检查失败后停止它,以便它不检查其余表达式。怎么了?
答案 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?)
因此,如果原子组内没有匹配项,它将遍历所有选项。 您可以改用条件句:
?\ s * \ b(?(?= a)a(?:bbr | cronym | ddress | pplet | r(?:ea | ticle || side | udio)?|(?(?= b)b(?:ase | asefont | d [io] | ig | lockquote | ody | r | utton)?|(?(?= c)c(?:anvas | aption | enter | ite | ode | ol( ?:group)?)|(?(?(d = d)d(?:ata(?:list)?| [dlt] | el | etails | fn | ialog | i [rv])|(?(?= e )em(?:bed)?|(?(?= f)f(?:i(?:eldset | g(?:caption | ure))| o(?:nt | oter | rm)| rame(? :set)?)|(?(?(h = h)h(?:[1-6r] | ead(?:er)?| tml)|(?(?(i = i)i(?:frame | mg | nput | ns)?|((?(?= k)kbd |(?(?= l)l(?:abel | egend | i(?:nk)?)|((?(?= m)m(?:a (?:in | p | rk)| et(?:a | er))|(?(?= n)n(?:av | o(?:frames | script))|(?(?= o) o(?:bject | l | pt(?:group | ion)| utput)|(?(?= p)p(?:aram | icture | regress)?|(?(?= q)q | (?(?= r)r [pt] |(?(?= r)红宝石|(?(?= s)s |(?(?= s)s(?:amp | ection | elect | mall | ource | pan | trike | trong | tyle | ub | ummary | up | vg)|(?(?= t)t(?:able | body | [dhrt] | emplate | extare |足|头| ime |发痒|机架)|(?(?(?= u)ul?|(?(?= v)v(?:ar | ideo)| wbr)))))))))))))))))))))))))))) )\ b