正则表达式学习笔记
前言
很久以前就开始使用正则表达式,一直浅尝则止,知其然不知其所以然,前几天,在重构同事代码中的正则表达式时,遇到拦路虎,花了一个星期的业余时间,终于将正则表达式使用完全掌握,是为记
目录
一. 正则表达式是一个DSL
二. 正则表达式引擎
三. 语言元素
四. 参考
一. 正则表达式,事实上就是一个编程语言 (文本匹配DSL)
学习正则表达式,一定要把正则表达式作为一种编程语言,一种领域特点语言,在正则表达式引擎解释下执行,具有常规语言的流程结构,如下:
顺序:默认
分支:[] |
循环:+ ? * {m,n}
封装:(子表达式)
二. 正则表达式引擎
DFA:从字符串中一个个取元素比较正则表达式
NFA:从正则表达式中取元素检查字符串
采用贪婪算法(尽量多匹配),性能可能稍差但支持更多功能如下:
捕获组、反向引用和$number引用方式;
环视(Lookaround,(?<=…)、(?<!…)、(?=…)、(?!…)),或者有的有文章叫做预搜索;
忽略优化量词(??、*?、+?、{m,n}?、{m,}?),或者有的文章叫做非贪婪模式;
占有优先量词(?+、*+、++、{m,n}+、{m,}+,目前仅Java和PCRE支持),固化分组(?>…)。
三. 语言元素
1. 占有字符和零宽度
占有字符:匹配并且将前移匹配点,如:
[0-9a-zA-Z]
\n
.\w\d
零宽度:匹配但不前移匹配点,如:
^$\b
(?=…)、正向肯定零宽断言
(?!…)、正向否定
(?<=…)、反向肯定
(?<!…)、反向否定
例如:
(?<=<(\w+)>).*(?=<\/ \1>)
匹配不包含属性的简单HTML标签内里的内容(注意\/是反斜线+斜线)
2. 子表达式
捕获并保存结果,用于后续使用
(exp) 子表达式, 同时进行捕获,如果不匹配使用前述零宽断言,如果不捕获使用(?:Exp)
\n前向引用子表达式, 如果捕获使用(\n),
(?<name>Exp) 命名子表达式
(?<name>) 前向引用明名子表达式
性能优化:(?>exp) 非回溯 或 贪婪匹配,如贪婪匹配不成功不尝试其他分支。
3. 或
(exp1|exp2|exp3)
4. 匹配次数限定符
*: 匹配零次或多次
+: 一次或多次
?:零次或一次
{n}: 精确匹配n次
{m,n}: 匹配次数在m到n之间
{n,}:匹配次数大于n
惰性匹配:在后面加?, 优先匹配次数少的, 如*?, +?, ??, {n,m}?, {n,}?
5. 优先级
正则表达式的计算方式与算术表达式非常类似;即从左到右进行计算,并遵循优先级顺序。
下表按从高到低的顺序包含了正则表达式运算符的优先级顺序。
运算符 |
说明 |
\ |
转义符 |
(), (?:), (?=), [] |
括号和中括号 |
*、+、?、{n}、{n,}、{n,m} |
限定符 |
^、$、\任何元字符 |
定位点和序列 |
| |
替换 |
字符具有高于替换运算符的优先级,例如,允许“m|food”匹配“m”或“food”。
四. 参考
http://blog.csdn.net/lxcnn 雁过无痕的博客
msdn正则表达式