【问题标题】:REGEX: PCRE atomic group doesn't work正则表达式:PCRE 原子组不起作用
【发布时间】:2018-08-27 14:51:13
【问题描述】:

在我的 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 检查失败后停止它,因此它不会检查表达式的其余部分。怎么了?

【问题讨论】:

  • 哇,对于这么短的字符串来说,这是一个长模式。你能提供更多你想要匹配的字符串的例子吗?
  • @UnbearableLightness:我正在尝试匹配字符串中的任何 HTML 标签。匹配步骤很好,但是检查不是 HTML 标签的其他标签(等 XML)的步骤太多了(GET
  • 这是因为正则表达式的性能对我来说很重要

标签: regex pcre


【解决方案1】:

我假设您在这里使用正则表达式知道自己在做什么,因为可能有人认为 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) 告诉引擎在那个时候提交匹配。如果没有找到匹配,它甚至不会再次尝试从&lt;/ 开始的匹配。

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

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

【讨论】:

    【解决方案2】:

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

    在当前位置,找到第一个匹配原子分组内的模式的序列并坚持下去。 (来源: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(?: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(?:[1-6r]|ead(?:er)?|tml)|(?(?=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|re|rogress)?|(?(?=q)q| (?(?=r)r[pt]|(?(?=r)ruby|(?(?=s)s|(?(?=s)s(?:amp|ection|elect|mall|ource |pan|trike|trong|tyle|ub|ummary|up|vg)|(?(?=t)t(?:able|body|[dhrt]|emplate|exarea|foot|head|ime|itle|rack )|(?(?=u)ul?|(?(?=v)v(?:ar|ideo)|wbr))))))))))))))))))))) )\b

    Regex101

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-20
      • 2011-08-12
      • 2014-08-02
      • 1970-01-01
      • 1970-01-01
      • 2014-01-01
      相关资源
      最近更新 更多