简单备忘正则表达式的原理、基本使用方法,和一些常见的优化方法。目的看懂网上摘抄的正则表达式,避免使用效率过低的正则。
原理
正则文法分为确定型有限状态自动机(DFA)和非确定型优先状态自动机(NFA),两种正则匹配算法能力相同,效率有区别。
- NFA 表达式主导
从表达式的第一部分开始,每次检查一部分,同时检查当前文本是否匹配,如果是,则继续表达式的下一部分,如此继续,直到表达式的所有部分都能匹配。整个过程,控制权在表达式的元素之间转换,因此被称为表达式主导"。 - DFA 文本主导
DFA在读入一个文本的时候,会记录当前有效的所有匹配的表达式位置。被扫描的字符串控制了引擎执行过程。
构造DFA会消耗更多的时间和内存。但是DFA构造好了以后执行效率更理想。NFA在匹配的过程中,存在大量的分支和回溯。Java、JavaScript等语言使用NFA,MySQL使用DFA。
语法
- 元字符
字符 | 说明 |
---|---|
. | 除换行符外所有字符 |
\w | 字母、数字、下划线、汉字 |
\d | 数字 |
\s | 空白符 |
\b | 匹配单词 |
^ | 字符串开始 |
$ | 字符串尾 |
- 量词
语法 | 说明 |
---|---|
* | 重复零次或更多次 |
+ | 重复一次或更多次 |
? | 重复零次或一次 |
{n} | 重复n次 |
{n,} | 重复n次或更多次 |
{n,m} | 重复n到m次 |
- 分组,反向引用
- 使用
()
进行分组匹配 - 使用
\1\2
按顺序反向引用分组内容 - 使用
(?<name>exp)
捕获到名称为name的分组 - 使用
(?:exp)
匹配exp,不捕获匹配分组,也不分配组号
- 匹配量词
在正则表达式次数限定符后增加该量词,可以指定匹配规则。
名称 | 方法 | 说明 |
---|---|---|
Greedy:贪婪 | 默认 | 匹配最长。在贪婪量词模式下,正则表达式会尽可能长地去匹配符合规则的字符串,且会回溯。 |
Reluctant :非贪婪,懒惰 | ? | 匹配最短。在非贪婪量词模式下,正则表达式会匹配尽可能短的字符串。 |
Possessive :独占 | + | 同贪婪一样匹配最长。不过在独占量词模式下,正则表达式尽可能长地去匹配字符串,一旦匹配不成功就会结束匹配而不会回溯。 |
- 其他
- 使用
\
进行转义 - 使用
|
表示或 - 使用
[]
表示区间条件
优化
- 合理使用括号
当要捕获组的时候,使用非捕获型括号(?:),这是写策略正则最常用的优化方法,因为使用(?:)可以匹配想要的内容,但不捕获到组里,可以节省资源,提高效率。 - 尽量使用非贪婪模式
尽量使用非贪婪模式,因为贪婪模式情况下,容易造成回溯。 - 使用字符组代替分支条件
使用[a-d]表示a~d之间的字母,而不是使用(a|b|c|d) - 谨慎用点号元字符,尽可能不用星号和加号这样的任意量词
例子: 要匹配 <12345>,其中<>中间是1-5位的数字
正常写法: <\d*>
优化写法: <\d{1,5}> - 使用占有优先量词和固化分组
占有优先量词:?+ *+ ++ {m,n}+
占有优先量词与匹配优先量词很相似,只是它们从来不会交还已经匹配的字符。
固化分组:(?>exp)
固化分组的内容与正常的匹配并无区别,只是当匹配完括号中的内容后,括号中的备用状态会全部舍去。
网友评论