快速入门
教程
工具和语言
示例
参考
书评
正则表达式教程
简介
目录
特殊字符
不可打印字符
正则表达式引擎内部
字符类
字符类减法
字符类交集
简写字符类
单词边界
交替
可选项
重复
分组和捕获
反向引用
反向引用,第 2 部分
命名组
相对反向引用
分支重置组
自由间距和注释
Unicode
模式修饰符
原子分组
占有量词
前瞻和后顾
环视,第 2 部分
将文本排除在匹配之外
条件
平衡组
递归
子例程
无限递归
递归和量词
递归和捕获
递归和反向引用
递归和回溯
POSIX 方括号表达式
零长度匹配
继续匹配
本网站上的更多内容
简介
正则表达式快速入门
正则表达式教程
替换字符串教程
应用和语言
正则表达式示例
正则表达式参考
替换字符串参考
书评
可打印 PDF
关于本网站
RSS 提要和博客
RegexBuddy—Better than a regular expression tutorial!

正则表达式引擎内部工作原理初探

了解正则表达式引擎的工作原理,可以帮助你更轻松地编写更好的正则表达式。这有助于你快速理解为什么特定的正则表达式没有达到你最初的预期。当你需要编写更复杂的正则表达式时,这可以为你节省大量猜测和苦思冥想的时间。

在介绍了一个新的正则表达式标记后,本教程将逐步解释正则表达式引擎如何实际处理该标记。这种内部观察在某些时候可能看起来有点冗长。但了解正则表达式引擎的工作原理使您可以充分利用其功能并帮助您避免常见错误。

虽然有许多正则表达式的实现,它们在语法和行为上有时略有不同,有时有很大不同,但基本上只有两种正则表达式引擎:文本导向引擎和正则表达式导向引擎。几乎所有现代正则表达式风格都基于正则表达式导向引擎。这是因为某些非常有用的功能,例如惰性量词反向引用,只能在正则表达式导向引擎中实现。

正则表达式导向引擎遍历正则表达式,尝试将正则表达式中的下一个标记与下一个字符匹配。如果找到匹配项,引擎将通过正则表达式和主题字符串前进。如果标记无法匹配,引擎会回溯到正则表达式和主题字符串中的先前位置,它可以在其中尝试通过正则表达式的不同路径。本教程稍后将详细介绍回溯。使用正则表达式导向引擎的现代正则表达式风格具有许多功能,例如原子分组独占量词,使您可以控制此回溯。

文本导向引擎遍历主题字符串,尝试正则表达式的所有排列,然后再前进到字符串中的下一个字符。文本导向引擎从不回溯。因此,没有太多关于文本导向引擎的匹配过程的讨论。在大多数情况下,文本导向引擎会找到与正则表达式导向引擎相同的匹配项。

当本教程讨论正则表达式引擎内部时,讨论假设了一个正则表达式导向引擎。它只在它们找到不同匹配项的情况下提到文本导向引擎。这只有在您的正则表达式使用交替时才会发生,其中两个备选方案可以在相同位置匹配。

正则表达式引擎始终返回最左边的匹配项

这是一个非常重要的理解点:正则表达式引擎始终返回最左边的匹配项,即使稍后可以找到“更好的”匹配项。在将正则表达式应用于字符串时,引擎从字符串的第一个字符开始。它尝试在第一个字符处正则表达式的所有可能排列。只有在尝试了所有可能性并发现失败后,引擎才会继续使用文本中的第二个字符。同样,它尝试正则表达式的所有可能排列,顺序完全相同。结果是正则表达式引擎返回最左边的匹配项。

在将 cat 应用于 He captured a catfish for his cat. 时,引擎尝试将正则表达式中的第一个标记 c 与匹配项中的第一个字符 H 进行匹配。此操作失败。此正则表达式没有其他可能的排列,因为它仅由一系列文本字符组成。因此,正则表达式引擎尝试将 ce 进行匹配。此操作也失败,将 c 与空格进行匹配也失败。到达字符串中的第 4 个字符时,c 匹配 c。然后,引擎尝试将第二个标记 a 与第 5 个字符 a 进行匹配。此操作也成功。但是,然后,t 无法匹配 p。此时,引擎知道无法从字符串中的第 4 个字符开始匹配正则表达式。因此,它继续使用第 5 个字符:a。同样,c 无法在此处进行匹配,引擎继续进行。在字符串中的第 15 个字符处,c 再次匹配 c。然后,引擎继续尝试在字符 15 处匹配正则表达式的其余部分,并发现 a 匹配 at 匹配 t

可以在字符 15 处开始匹配整个正则表达式。引擎“急于”报告匹配项。因此,它将 catfish 的前三个字母报告为有效匹配项。引擎从不继续执行此操作,以查看是否存在任何“更好的”匹配项。第一个匹配项被认为足够好。

在此引擎内部的第一个示例中,我们的正则表达式引擎似乎只像常规文本搜索例程一样工作。但是,重要的是您可以在自己的脑海中遵循引擎执行的步骤。在以下示例中,引擎的工作方式对其找到的匹配项产生了深远的影响。某些结果可能令人惊讶。但是,一旦您了解引擎的工作原理,它们始终是合乎逻辑且预先确定的。