正则表达式的匹配原理
1. 概述
1.1 不同语言或工具中使用正则表达式的注意事项
- 支持的元字符及其意义, 这通常称为正则表达式的 “流派”
- 交互方式(如何进行正则表达式的操作, 容许进行哪些操作, 操作的目标文本类型等)
- 正则表达式引擎如何将表达式应用到文本
1.2 引擎类型
| 引擎类型 | 程序 |
|---|---|
| DFA | awk(大多数版本)、egrep(大多数版本)、flex、lex、MySQL、Procmail |
| 传统型 NFA | GUN Emace、Java、grep(大多数版本)、less、moer、.NET、PCRE library、Perl、PHP、Python、Ruby、sed、vi |
| POSIX NFA | mawk、Mortice Kern Systems’utilities、GNU Emacs 明确指定时使用 |
| DFA/NFA 混合 | GUN awk、GUN grep/egrep、Tcl |
1.3 各引擎通用原则
- 优先选择最左端的匹配结果(最靠开头)
- 标准匹配量词的匹配优先(*、+、? 和{m, n}), 贪婪模式
- 在多选结构中,不要将大范围的表达式放在小范围表达式范围之后,会导致永远无法匹配
1.4 引擎的构造
- 文字文本 : 字符是否与当前尝试匹配的字符相同
- 字符组、点号、Unicode属性及其他 : 只匹配一个字符
- 捕获型括号 : 用于捕获文本的括号(而不是用于分组的括号)不会影响匹配的过程
- 锚点 : 简单锚点(^、$、\G、\b、…) 只检查目标字符串中的特定位置情况,或者是比较两个相邻的字符(\<、\b…); 复杂锚点(环视)可以包含任意复杂的子表达式, 所有它们也可以任意复杂
- 括号、返向引用和忽略优先量词
2. 表达式主导与文本主导
2.1 非确定型有穷自动机 : NFA引擎, 表达式主导
- 表达式的控制权在不同的元素之间转换, 所以称为 “表达式主导”
- 引擎查看表达式一部分—>同时检查当前文本是否匹配表达式的当前部分—>是则继续匹配,直到表达式的所有部分都能匹配,则匹配成功
- NFA要翻来覆去吃字符、吐字符,速度慢,但是特性丰富,所以反而应用广泛
NFA 引擎在操作上的优点
- 实质上,在表达式主导的匹配过程中,每一个子表达式都是独立的, 子表达式之间不存在内在联系,只是整个正则表达式的组成部分
- 子表达式与正则表达式的控制结构的层级关系控制了整个匹配过程(控制结构包括多选分支、括号以及匹配量词)
2.2 确定型有穷自动机 : DFA引擎, 文本主导
- 引擎查看表达式一部分—>使用文本去匹配正则—>把有可能的匹配串全部标注出来—>再匹配正则表达式的下一个部分—>根据新的匹配结果更新标注
- DFA引擎对于文本串里的每一个字符只需扫描一次,比较快,稳定、但特性较少
2.3 NFA引擎的回溯(backtracking)
- NFA 引擎最重要的性质是, 它会依次处理各个子表达式或组成元素,遇到需要在两个可能中进行选择的时候,它会选择其一,同时记住另一个,以备稍后可能的需要
- 需要做出选择的情形包括量词和多选结构(决定是否尝试另一次匹配和决定选择哪个多选分支, 留下哪个稍后尝试)
- 如果正则表达式中余下的部分最终匹配失败,引擎会回溯到之前做出选择的地方,选择其他的备用分支继续尝试
本文探讨了正则表达式的两大引擎类型:NFA与DFA,并解释了它们的工作原理及特点。NFA引擎采用表达式主导的方式,通过回溯实现丰富的特性;而DFA引擎则采用文本主导的方法,虽然速度快但特性相对较少。

1400

被折叠的 条评论
为什么被折叠?



