`
jsycbc
  • 浏览: 8150 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

正则表达式之回溯

阅读更多
我们所使用的正则表达式的匹配基础大概分为:优先选择最左端(最靠开头)的匹配结果和标准的匹配量词(*、+、?和{m, n})是匹配优先的。
“优先选择最左端的匹配”顾名思义就是从字符串的起始位置开始匹配直到匹配结束这是基础;“标准匹配量词”又分为“非确定型有穷自动机(NFA)”也可以叫做“表达式主导”;另外一种是“确定型有穷自动机(DFA)”也可以叫做“文本主导”。我们目前在JavaScript中所使用的正则表达式为“表达式主导”。表达式主导和文本主导解释起来有些麻烦,先看来一个例子可能会清楚些
复制代码 代码如下:

// 使用正则表达式匹配文本
var reg = /to(nite|knight|night)/;
var str = 'doing tonight';
reg.test(str);

在上面的这个例子中,第一个元素[t],它将会重复尝试,直到目标字符串中找到‘t'为止。之后,就检查紧随其后的字符是否能由[o]匹配,如果能,就检查下面的元素(nite|knight|night)。它的真正含义是“nite”或者“knight”或者“night”。引擎会依次尝试这3种可能。尝试[nite]的过程是先尝试[n],然后[i],然后[t],最后是[e]。如果这种尝试失败,引擎会尝试另一种可能,如此继续下去,直到匹配成功或是报告失败。表达式中的控制权在不同的元素之间转换,所以称为“表达式主导”。

同样是上面的例子“文本主导”在扫描字符串时,会记录当前有效的所有匹配可。当引擎移动到t时,它会在当前处理的匹配可能中添加一个潜在的可能:
字符串中的位置 正则表达中的位置
……doing tonight 可能的匹配位置:/t↑o(nite|knight|nigth)/

接下来扫描的每个字符,都会更新当前的可能匹配序列。继续扫描两个字符以后的情况是:

字符串中的位置 正则表达中的位置
……doing tonight 可能的匹配位置:/to(ni↑te|knight|ni↑gth)/

有效的可能匹配变为两个(knight被淘汰出局)。扫描到g时,就只剩下一个可能匹配了。当h和t匹配完成后,引擎发现匹配已经完成,报告成功。“文本主导”是因为它扫描的字符串中的每个字符都对引擎进行了控制。

如果想要弄明白“表达式主导”是如何工作的,那就要看一下我们今天的主题“回溯(backtracking)”。回溯就像是在走岔路口,当遇到岔路的时候就先在每个路口做一个标记。如果走了死路,就可以照原路返回,直到遇见之前所做过的标记,标记着还未尝试过的道路。如果那条路也走不能,可以继续返回,找到下一个标记,如此重复,直到找到出路,或者直到完成所有没有尝试过的路。

在许多情况下,正则引擎必须在两个(或更多)选项中做出选择。当遇到/……x?……/时,引擎必须是否尝试匹配X。对于/……X+……/的情况,毫无疑问,X至少尝试匹配一次——因为加号要求必须匹配至少一次。第一个X匹配之后,此要求已经满足,需要决定是否尝试下一个X。如果决定进行,还要决定是否匹配第三个X,第四个X,如此继续。每次选择,其实就是做一个标记,用于提示此处还有另一个可能的选择,保留起来以备用。在回溯的过程中要考虑两个要点:哪个分支应当首先选择?回溯的时候使用的是哪个(或者是哪些个)之前保存的分支?

第一个问题是按下面这条重要原则来选择的:

如果需要在“进行尝试”和“路过尝试”之间选择,对于匹配优先量词,引擎会优先选择“进行尝试”,而对于忽略优先量词,会选择“路过尝试”。

第二个问题是按以下这条原则:

距离当前最近储存的选项就是当本地失败强制回溯时返回的。使用的原则是LIFO(last in first out,后进先出)。

我们先来看几个在道路中做标记的例子:

1、未进行回溯的匹配

用[ab?c]来匹配“abc”。[a]匹配之后,匹配的当前状态如下:
“a↑bc” a↑b?c

现在轮到[b?]了,正则引擎需要决定:是需要尝试[b]呢,还是跳过?因为[?]是匹配优先的,它会尝试匹配。但是,为了确保在这个尝试最终失败之后能够恢复,引擎会把:
“a↑bc” ab?↑c
添加到备用状态序列中。也就是说,稍后引擎可能从下面的位置继续匹配:从正则表达式中的[b?]之后,字符串的c之前(也就是说当前的位置)匹配。这实际上就是跳过[b]的匹配,而问题容许这样做。引擎做好标记后,就会继续向前检查[b]。在示例中,它能够匹配,所以新的当前状态变为:
“ab↑c” ab?↑c

最终的[c]也能成功匹配,所以整个匹配完成。备用状态不再需要了,所以不再保存它们。

2、进行了回溯的匹配

下面要匹配的文本是“ac”,在尝试[b]之前,一切都与之前的过程相同。显然,这次[b]无法匹配。也就是说,对[……?]进行尝试的路走不通了。因为有一个备用状态,这个“局部匹配失败”产工会导致整体匹配失败。引擎会进行回溯,也就是说,把“当前状态”切换为最近保存的状态。
“a↑c” ab?↑c

在[b]尝试之前保存的尚未尝试的选项。这时候,[c]可以匹配c,所以整个匹配宣告完成。

3、不成功的匹配

现在要匹配的文本是“abx”。在尝试[b]以前,因为存在问号,保存了这个备用状态:
“a↑bx” ab?↑c

[b]能够匹配,但这条路往下却走不通了,因为[c]无法匹配x。于是引擎会回溯到之前的状态,“交还”b给[c]来匹配。显然,这次测试也失败了。如果还有其他保存的状态,回溯会继续进行,但是此时不存在其他状态,在字符串中当前位置开始的整个匹配也就宣告失败。
分享到:
评论

相关推荐

    C语言正则表达式库

    3. **回溯算法**:PCRE库使用了高效的回溯算法来执行正则表达式匹配。虽然这可能会导致性能问题,但通过优化的匹配引擎和使用预编译模式,可以显著提高效率。 4. **匹配选项**:提供了许多可配置的匹配选项,例如不...

    正则表达式 必知必会 pdf

    本书基于各种实用场景,从基础的文本匹配开始,逐步深入到回溯引用、条件性求值以及前后查找等高级特性,使得读者能够系统、全面地掌握正则表达式的使用方法,并将其应用于解决实际问题中。 书中介绍的正则表达式...

    Delphi2010正则表达式插件

    《Delphi 2010正则表达式插件详解》 在编程世界中,正则表达式(Regular Expression)是一种强大的文本处理工具,能够帮助开发者高效地进行字符串的匹配、查找、替换等操作。在Delphi 2010这个经典的集成开发环境中...

    精通正则表达式(第三版)简体中文版

    ### 正则表达式基础知识与应用 #### 一、正则表达式的定义及用途 正则表达式(Regular Expression)是一种强大的文本处理工具,能够帮助用户查找、替换以及操作特定的字符串或字符组合。它在多种编程语言和操作...

    正则表达式调试工具

    2. **步骤跟踪**:通过逐步执行正则引擎的匹配过程,帮助开发者理解正则表达式的匹配逻辑,尤其是在面对复杂的嵌套或回溯情况时。 3. **经典例程**:内建了各种经典的正则表达式示例,方便学习和参考,有助于开发者...

    正则表达式学习资料以及练习项目代码很多

    - **正则表达式性能优化**:避免过度复杂的正则表达式,合理使用非贪婪匹配,减少回溯。 - **正则表达式调试**:使用`re.DEBUG`标志编译正则表达式,查看其内部结构。 - **正则表达式在其他语言中的差异**:虽然...

    正则表达式之道.rar

    《正则表达式之道》是一本深入探讨正则表达式的资源集合,旨在帮助读者掌握这一强大的文本处理工具。正则表达式(Regular Expression)是一种模式匹配语言,它用于在字符串中进行查找、替换和提取特定模式的操作。在...

    源码(精通正则表达式&实战正则表达式)

    本资源“源码(精通正则表达式&实战正则表达式)”专注于JavaScript环境下的正则表达式学习,通过一系列视频教程和配套源码,帮助开发者提升对正则表达式的理解和应用能力。 首先,"精通正则表达式五部视频"可能涵盖...

    正则表达式工具类,正则表达式封装,Java正则表达式

    在Java编程语言中,正则表达式是一种强大的文本处理工具,用于匹配、查找、替换等操作。本节我们将深入探讨正则表达式工具类`RegUtils`,它封装了正则表达式的常用功能,便于在实际开发中进行复用。 首先,`...

    正则表达式综合练习

    正则表达式(Regular Expression,简称regex)是用于匹配字符串的一种模式,它在IT行业中扮演着重要的角色,尤其是在数据处理、文本分析、爬虫技术等领域。正则表达式通过使用预定义的字符集和特殊符号,可以高效地...

    正则式工具(自动生成正则表达式)

    正则式,全称为“正则表达式”,是编程领域中一种强大的文本处理工具,用于匹配、查找、替换和分析字符串。它通过一系列特定的字符和语法构建模式,可以高效地处理各种复杂的文本匹配任务。在软件开发、数据处理、...

    深入浅出之正则表达式

    正则表达式是一种强大的文本处理工具,用于模式匹配和数据提取。它们在编程语言、文本编辑器、搜索引擎等各类...通过深入学习正则表达式,不仅可以提高工作效率,还能提升编程能力,是每个程序员不可或缺的技能之一。

    [精通正则表达式(第三版)].(美)佛瑞德.扫描版-带详细目录书签.pdf

    此外,书中详述了正则表达式的回溯机制,这是理解正则表达式效率和性能的关键。回溯是当匹配失败时,正则引擎退回到上一步尝试其他可能性的过程。掌握回溯原理有助于编写更高效、避免无限循环的正则表达式。 《精通...

    正则表达式验证器,验证常用的编程语言的正则表达式

    正则表达式(Regular Expression,简称regex)是用于匹配字符串的一种模式,广泛应用于文本处理、数据验证、搜索和替换等场景。在编程中,正确构造和理解正则表达式至关重要,因为它们能帮助我们高效地处理字符串...

    精通正则表达式&正则表达式经典实例

    通过《精通正则表达式》这本书,你可以深入理解正则表达式的内部机制,学习高级特性如回溯、后向引用和递归等。而《正则表达式经典实例》则提供了大量实用示例,帮助你在实践中巩固所学,解决实际问题。 学习并掌握...

    正则表达式之道

    ### 正则表达式之道:深入解析与应用 正则表达式是一种强大的文本处理工具,其功能在于通过预设的模式来匹配、查找、替换文本中的字符串。它看似复杂,但掌握后能极大提高文本处理的效率。本文将详细介绍正则表达式...

    JavaScript正则表达式迷你书

    第4章阐释了正则表达式回溯法原理,讲解了没有回溯的匹配和有回溯的匹配,常见的回溯形式。回溯是正则表达式匹配时的一种现象,它会根据表达式进行尝试和回退,以找到匹配的结果。回溯在贪婪量词和惰性量词匹配时会...

    delphi正则表达式包

    Delphi正则表达式包是为Delphi 7开发者设计的一款强大的文本模式匹配工具,它引入了Perl风格的正则表达式支持。正则表达式(Regular Expression)是一种用于匹配字符串的强大工具,常用于文本搜索、替换和数据提取等...

Global site tag (gtag.js) - Google Analytics