【问题标题】:Are atomic groups always used with alternation | inside?原子团总是交替使用吗?里面?
【发布时间】:2014-06-08 10:56:56
【问题描述】:

原子组是否总是在内部交替使用|?我的印象是“组内任何令牌记住的所有回溯位置”from

原子组是一个组,当正则表达式引擎从中退出时, 自动丢弃任何人记住的所有回溯位置 组内的令牌。原子团是非捕获的。语法 是(?>组)。

一个例子将使原子组的行为变得清晰。常规的 表达式 a(bc|b)c(捕获组)匹配 abcc 和 abc。正则表达式 a(?>bc|b)c(原子组)匹配 abcc 但不匹配 abc。

你能举个例子,其中使用原子组而不在其中使用|?谢谢。

【问题讨论】:

  • 经典的:(?>a+)a 总是失败。
  • "(?>a+b*)+" 而不是"(?:a+b*)+",以避免使用这种字符串的灾难性回溯:"ababbaaaabbababaabba
  • 比较 (abc)?a(?>(abc)?)a。只有第一个在“abc”中找到匹配项。

标签: regex


【解决方案1】:

交替与原子团无关。原子团的重点是避免回溯。这主要有两个原因:

  1. 当正则表达式无论如何都将无法匹配时,请避免不必要的回溯。
  2. 避免回溯到您不想找到匹配项的表达式部分

您要求提供一个没有交替的原子分组示例。

让我们看看这两种用途。

A.避免失败时回溯

例如,考虑以下两个字符串:

name=Joe species=hamster food=carrot says:{I love carrots} 
name=Joe species=hamster food=carrot says:{I love peas}

假设我们想要找到一个格式正确的字符串(它有key=value 标记)并且在标记之后有carrots,可能在says 部分。尝试这样做的一种方法可能是:

非原子版本

^(?:\w+=\w+\s+)*.*carrots

这将匹配第一个字符串而不是第二个。很高兴。或者……我们真的吗?不开心有两个原因。我们将在 B 部分中研究第二个原因(原子团的第二个主要原因)。那么第一个原因是什么?

好吧,当您在 RegexBuddy 中调试失败案例时,您会看到它在引擎决定它无法匹配第二个字符串之前执行引擎 401 步骤。之所以这么长,是因为在匹配令牌并且未能匹配says:{I love peas} 中的carrots 之后,引擎会回溯到(\w+=\w+\s+)*,希望在那里找到carrots。现在让我们看一个原子版本。

原子版本

^(?>(?:\w+=\w+\s+)*).*carrots

在这里,原子组防止引擎回溯到(?:\w+=\w+\s+)*。结果是在第二个字符串上,引擎在 64 个步骤中失败。比 401 快很多!

B.避免回溯到不需要匹配的字符串部分

保持相同的正则表达式,让我们稍微修改一下字符串:

name=Joe species=hamster food=carrots says:{I love carrots} 
name=Joe species=hamster food=carrots says:{I love peas}

我们的原子正则表达式仍然有效(它匹配第一个字符串但不匹配第二个字符串)。

但是,非原子正则表达式现在匹配两个字符串!那是因为在says:{I love peas}中找不到carrots后,引擎回溯到token中,在food=carrots中找到carrots

因此,在这种情况下,原子组是一种方便的工具,可以跳过我们不想找到 carrots 的字符串部分,同时仍确保其格式正确。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-24
    • 1970-01-01
    • 2012-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多