正则表达式用于对字符串进行匹配。
一:匹配模式文本:
正则表达式的匹配模式文本常包括以下内容:
元字符:拥有特殊含义的字符;
元字符 | 说明 |
. | 匹配除换行符以外的任意字符 |
w | 匹配字母、数字;C#中还支持汉字;等价于[a-zA-Z0-9] |
W | 与上相反,匹配非数字字母;等价于[^a-zA-Z0-9] |
s | 匹配空白字符 |
S | 与上相反,匹配非空白字符 |
d | 匹配数字 |
D | 与上相反,匹配非数字 |
匹配单词开始或者结束的位置 | |
B | 与上相反,匹配非单词开始或者结束的位置 |
^ | 匹配字符串开始的位置 |
$ | 匹配字符串结束的位置 |
表示重复次数的:
类别 | 说明 |
? | 表示左边的部分重复0次或者1次,或者表示非贪婪模式 |
* | 表示左边的部分重复0次或者多次 |
+ | 表示左边的部分重复1次或者多次 |
{min, max} | 表示左边的部分重复min次到max次 |
{min, } | 表示左边的部分重复最少min次 |
{num} | 表示左边的部分重复num次 |
表示分组的 :
分类 | 格式 | 说明 |
捕获 | (abc) | 匹配abc,分组,组名从1开始依次增加1;捕获文本分别保存到当前的分组和分组0中。 |
(?<name>abc) | 匹配abc,分组,组名为name,捕获文本分别保存到name组里和分组0中。 | |
(?:abc) | 匹配abc,不分组,捕获匹配文本只保存到分组0中,相当于直接abc | |
断言 | (?=abc) | 当前位置后面必须要有字符"abc",但是不匹配abc。位置不移动 |
(?<abc) | 当前位置前面必须有字符"abc",但是不匹配abc.位置不移动 | |
(?!abc) | 当前位置后面不是字符"abc",但是不匹配后面字符.位置不移动 | |
(?<!abc) | 当前位置前面不是字符"abc",但是不匹配前面字符.位置不移动 | |
注释 | (?#comment) | 注释 |
其他:
类别 | 说明 |
[abc] | 匹配括号中的abc中的任意一个(必须要匹配一个字符) |
[^abc] | 匹配除括号中字符以外的一个字符(必须要匹配一个字符) |
| | 表示 或;匹配 | 前面的模式 或 后面的模式 |
char | 匹配特殊字符,如*匹配*;?匹配? |
um | 表示第num个捕获型括号捕获的文本(括号计数是按照左括号出现的顺序算的,注意嵌套括号) |
k<name> | 反向引用分组名为name保存的文本 |
二、原理
例子:
- 待匹配字符串:777442ww问问;
- 正则表达式为:^([0-9])1{2}(?<qq>4)k<qq>2ww(?=问问)。
- 调试工具: MTracer.exe 。
^表示字符串开始;([0-9])表示开始的第1个字符是数字并为其分组,默认组名是1;1{2}表示第2、3两个字符与组名为1的内容一样,即与第一个字符一样;(?<qq>4)表示第4个字符是数字4并分组,组名显式指定为"qq",k<qq>表示第5个字符与组名为"qq"的内容一致;"2ww"表示后面的内容为"2ww";(?=问问)为零宽度断言,表示"2ww"后面要有"问问",但是不捕获"问问"。也不为其分组。
如图:图中下方为分组的内容,分组0为成功匹配整个正则表达式的文本,分组1为第一个带()而没有显式指定组名的,本例为([0-9]),命名为"qq"的自然就是(?<qq>4)。
以下内容以该例子讲解。
1、基本概念:
- 位置:指的不是具体字符的位置,而是字符的前后的位置。
如下图所示:
- 匹配:是指字符串与正则表达式进行比较,符合准则要求则匹配成功;
- 捕获:匹配成功后,截取匹配成功的长度为n的字符串保存到分组0,地址向前移动n位;
- 分组:用()包裹的正则表达式,用于保存匹配成功时捕获的文本,以便在后面需要时反向引用。分组0表示整个正则表达式匹配的文本。
- 反向引用:调用前面的分组中匹配成功的字符串。
- 零宽度断言:要求待匹配的字符串的左侧或者右侧符合某些要求,断言不捕获文本,位置不变。环视
- 与零宽度断言类似不捕获文本且地址不移动的有:单词边界;行的起始、结束。
2、分组与反向引用
- 分组:
格式如下
(abc) | 匹配abc,分组,组名从1开始依次增加1;捕获文本分别保存到当前的分组和分组0中。 |
(?<name>abc) | 匹配abc,分组,组名为name,捕获文本分别保存到name组里和分组0中。 |
格式:(abc)表示分组不显式指定分组名,(?<name>abc)则显式的指定分组名。
系统自动分配组名为0的分组用于保存匹配整个正则表达式的文本;对于未显式命名的分组,系统用数字分配组名,从1开始依次增加1;捕获文本分别保存到当前的分组和分组0中;显式命名组名时,应避免使用数字命名,以避免与系统命名的分组名冲突。
- 引用:
在正则表达式中引用前面定义的分组匹配成功后保存的文本而不是分组中的正则表达式,当然也可以是默认的分组0。
如例子中的([0-9])1,系统未分组分配组名为1,分组的正则表达式[0-9]捕获数字7,并将7保存到分组1和分组0中。反向引用时引用的是数字7,而不是[0-9].
- 引用数字(系统分配的组名):用int,如例子中的1,表示引用分组1中保存的文本。正则最多将 3 位数字识别为反向引用,如果想在反向引用如 1后,再匹配一个数字 2 ,写成12,系统会认为是反向引用分组12,此时应该写成 012。
- 引用字符(显式定义的组名):使用k<name>或 k'name';如例子中k<qq>,引用分组qq中保存的文本。
注意:反向引用引用的是该正则表达式已经匹配成功的文本。而重复次数则是指重复正则表达式而不是匹配的文本。当然如果重复次数左边是反向引用,如例子中的1{2},{2}表示重复正则表达式1,也就变成了 11,自然就是重复分组1中保存的文本了。
3、匹配过程。
正则表达式按顺序自左向右对待匹配的字符串进行匹配。首先正则表达式“定位”到目标字符串的起始位置0;首先^取得控制权,检测位置0是不是字符串开始的位置,经检测是,继续向下执行,但位置不移动;将控制权传给表达式([0-9])(表示1个数字,且将该分组默认命名为1),成功匹配数字7,将数字7保存到分组0,地址移动到位置1处;控制权转交给表达式1{2}(表示匹配2个与分组1中的数字相同的数字,由于分组1中匹配的数字为7,因此这里为2个7),从位置1处向后成功捕获2个数字7,此时地址移动到位置3处;控制权转交给表达式(?<qq>4)(表示匹配数字4,并且分组,组名为"qq"),在位置3处后面有一个数字4,匹配成功,将4保存到分组"qq"和分组0,地址移动到位置5处;控制权转交给表达式 2ww(表示匹配字符"2ww"),在位置5处向后成功匹配字符"2ww"后,地址移动到位置8处;控制权转交给表达式(?=问问)(表示零宽度断言,即在位置8的后面有2个字符"问问",但是不捕获它们,也不为其分组),经检测成功,退出匹配过程。
参考:
http://www.cnblogs.com/webyihui/p/3984615.html
http://www.cnblogs.com/AaronYang/p/3979710.html
http://www.cnblogs.com/coco1s/p/4008955.html
http://www.cnblogs.com/Zjmainstay/p/my-regexp.html
http://www.cnblogs.com/xjchenhao/p/4016515.html
http://www.cnblogs.com/ayqy/p/3879397.html
http://www.cnblogs.com/dwlsxj/p/Regex.html#!comments
http://www.cnblogs.com/dwlsxj/p/Reg.html
http://www.cnblogs.com/dwlsxj/p/Regex-3.html