【发布时间】:2019-02-06 18:37:50
【问题描述】:
我正在尝试从多个来源研究正则表达式,但遇到了关于回溯的困惑,因为一个定义回溯,它意味着正则表达式引擎无法匹配模式时的状态,因此它回溯到位置 匹配第一个原子的位置,例如,要匹配He captured a catfish for his cat 中的cat,引擎将如下所示:
- 它将搜索
c,直到匹配到cincaptured - 那么
a也一样 - 但无法将
t与p匹配 - 引擎在
captured中重置到c之后的位置,因为它知道在此之前不会发生匹配。
因此,在所有没有量词的情况下,引擎将重置整个模式以尝试从不同位置再次匹配它。
另一个将回溯定义为使用像.* 这样的量词的状态,因此正则表达式引擎将匹配完整的文本,从而使其失败,因此它会一个接一个地回溯,直到匹配发生。我认为这些不一样。
如here所述:
正则表达式匹配的一个基本特征涉及称为回溯的概念。它被所有正则表达式量词使用(在需要时),即 *、*?、+、+?、{n,m} 和 {n,m}?。
要匹配一个正则表达式,整个正则表达式必须匹配,而不仅仅是它的一部分。因此,如果包含量词的模式的开头成功导致模式中的后面部分失败,则匹配引擎会备份并重新计算开头部分 - 这就是它被称为回溯的原因。
这意味着像 ([A-Z][A-Z0-9]*)\b[^>]*>.*<\/\1> 这样匹配 Testing <B><I>bold italic</I></B> text. 的模式将像这样工作:
- 它将首先匹配
<B> - 那么模式需要匹配
.*,它将匹配到字符串的末尾。 - 然后它会尝试匹配
<,但它已经到达末尾,所以它会一个一个地回溯直到匹配。
与第一个 cat 示例相反,它将引擎完全重置到第一个原子并从匹配第一个原子的位置重新开始。
但在另一种情况下,如果我在.* 之后添加?,正则表达式会跳过这个原子.*? 尝试匹配剩余的字符,但如果不匹配,它会回退到. 匹配直到有一个<,然后在它之后开始匹配原子。
我认为这里有多种定义,谁能解释一下这些案例中的哪一个是回溯。
【问题讨论】:
-
其实是的,它们是一样的。考虑
ca+?t(它使用一个量词)——它的回溯与您的样本输入上的cat完全相同 -
@WiktorStribiżew 我认为你是对的,所以我对这个问题进行了一些编辑,我需要重新考虑并添加关于每个案例的更多细节,并以你的评论作为答案。
-
网上看了一些,看来回溯的重点是"正则表达式引擎回到之前保存的状态继续搜索匹配”.
-
当存在非固定长度的量词和交替构造时,可能会发生这种情况。只是 matching 的方式与贪婪(尽可能地抓取,然后从抓取的文本末尾逐个字符地产生字符以适应下一个模式)和非贪婪(非-首先跳过贪婪模式,测试所有后续模式,然后“扩展”非贪婪模式,再抓取一个字符,然后再次尝试后续模式)量词。
标签: regex