匹配行为

更新:2007 年 11 月

.NET Framework 正则表达式引擎是回溯的正则表达式匹配器,它并入了传统的非确定性有限自动机 (NFA) 引擎(例如 Perl、Python、Emacs 和 Tcl 使用的引擎)。这使其有别于更快的、但功能更有限的纯正则表达式确定性有限自动机 (DFA) 引擎,例如在 awk、egrep 或 lex 中提供的那些引擎。这也使其有别于标准化的、但较慢的 POSIX NFA。

三种正则表达式引擎类型

本节概述了三种引擎类型的优缺点,并解释了 .NET Framework 引擎为什么实现传统的 NFA 匹配器。

DFA 引擎在线性时状态下执行,因为它们不要求回溯(并因此它们永远不测试相同的字符两次)。DFA 引擎还可以确保匹配最长的可能的字符串。但是,因为 DFA 引擎只包含有限的状态,所以它不能匹配具有反向引用的模式;并且因为它不构造显示扩展,所以它不可以捕获子表达式。

传统的 NFA 引擎运行所谓的“贪婪的”匹配回溯算法,以指定顺序测试正则表达式的所有可能的扩展并接受第一个匹配项。因为传统的 NFA 构造正则表达式的特定扩展以获得成功的匹配,所以它可以捕获子表达式匹配和匹配的反向引用。但是,因为传统的 NFA 回溯,所以它可以访问完全相同的状态多次(如果通过不同的路径到达该状态)。因此,在最坏情况下,它的执行速度可能非常慢。因为传统的 NFA 接受它找到的第一个匹配,所以它还可能会导致其他(可能更长)匹配未被发现。

POSIX NFA 引擎与传统的 NFA 引擎类似,不同的一点在于:在它们可以确保已找到了可能的最长的匹配之前,它们将继续回溯。因此,POSIX NFA 引擎的速度慢于传统的 NFA 引擎;并且在使用 POSIX NFA 时,您恐怕不会愿意在更改回溯搜索的顺序的情况下来支持较短的匹配搜索,而非较长的匹配搜索。

程序员更为喜欢传统的 NFA 引擎的原因在于,NFA 引擎与 DFA 或 POSIX NFA 引擎相比更易于表达。尽管在最坏情况下 NFA 引擎的运行速度稍慢,但您可以通过使用降低多义性和限制回溯的模式,控制这些引擎以在线性时或多项式时状态下查找匹配。

.NET Framework 引擎功能

在充分利用传统 NFA 引擎优点的基础上,.NET Framework 正则表达式引擎包括了一组完整的构造,让程序员能够操纵回溯引擎。这些构造可被用于更快地找到匹配,或支持特定扩展,而非其他扩展。

其他功能包括:

  • “惰性”限定符:??、*?、+?、{n,m}?。这些惰性限定符指示回溯引擎首先搜索最少数目的重复。与之相反,普通的“贪婪的”限定符首先尝试匹配最大数目的重复。

  • 积极的预测先行。这允许回溯引擎在匹配子表达式后返回到文本中相同的作用点。这对于通过验证起始于相同位置的多个模式来搜索整个文本是很有用的。

  • 消极的预测先行。这增加了只在子表达式匹配失败的情况下才匹配表达式的能力。这对于删改一个搜索特别有用,因为与必须被包括在内的情况的表达式相比,应被排除的情况的表达式通常要简单得多。(例如,编写搜索不以“non”起始的单词的表达式就很困难)。

  • 条件计算。这允许引擎可以根据以前的子表达式匹配的结果,使用多个替换模式进行搜索。这提供了超越反向引用所允许的、更为强大的功能,例如,当以前在子表达式中捕获了左括号时匹配右括号。

  • 非回溯子表达式(也称作“贪婪”子表达式)。这允许回溯引擎确保子表达式只匹配为该子表达式找到的第一个匹配项,就好像该表达式独立于其包含的表达式运行。如果没有此构造,来自更大的表达式的回溯搜索可能会更改子表达式的行为。

  • 从右到左匹配。这在从右到左而非从左到右搜索的情况下十分有用,或者在从模式的右侧部分开始搜索比从模式的左侧部分开始搜索更为有效的情况下十分有用。

  • 积极的和消极的追溯。类似于预测先行。因为正则表达式引擎允许完全的从右到左匹配,所以正则表达式允许无限制的追溯。

请参见

其他资源

.NET Framework 正则表达式