1、元字符:
代码 | 说明 |
---|---|
. | 匹配除换行符以外的任意字符 |
/w | 匹配字母或数字或下划线或汉字 |
/s | 匹配任意的空白符 |
/d | 匹配数字 |
/b | 匹配单词的开始或结束 |
^ | 匹配字符串的开始 |
$ | 匹配字符串的结束 |
eg:[0-9]代表的含意与/d就是完全一致的:一位数字;同理[a-z0-9A-Z_]也完全等同于/w (只考虑EN)
2、使用转义字符:
如果你想查找元字符本身的话,比如查找. /或者* ,使用/来取消这些字符的特殊意义
例如:unibetter/.com匹配unibetter.com,C://Windows匹配C:/Windows
3、限定符:
代码/语法 | 说明 |
---|---|
* | 重复零次或更多次 |
+ | 重复一次或更多次 |
? | 重复零次或一次 |
{n} | 重复n次 |
{n,} | 重复n次或更多次 |
{n,m} | 重复n到m次 |
4、分支条件:
用|把不同的规则分隔开,满足其中一种规则即匹配
使用分枝条件时,要注意各个条件的顺序。匹配分枝条件时,将会从左到右地测试每个条件,如果满足了某个分枝的话,就不会去再管其它的条件了。(导致匹配结果多于预想)
5、子表达式(分组):
IP Adress Regular Expression:
((2[0-4]/d|25[0-5]|[01]?/d/d?)/.){3}(2[0-4]/d|25[0-5]|[01]?/d/d?)
2[0-4]/d|25[0-5]|[01]?/d/d?
6、反义:
代码/语法 | 说明 |
---|---|
/W | 匹配任意不是字母,数字,下划线,汉字的字符 |
/S | 匹配任意不是空白符的字符 |
/D | 匹配任意非数字的字符 |
/B | 匹配不是单词开头或结束的位置 |
[^x] | 匹配除了x以外的任意字符 |
[^aeiou] | 匹配除了aeiou这几个字母以外的任意字符 |
7、后向引用:
eg: /b(/w+)/b/s+/1/b
/b(?<Word>/w+)/b/s+/k<Word>/b
/b(?'Word'/w+)/b/s+/k'Word'/b
8、零宽断言:
(?=exp) 自身出现的位置的后面能匹配表达式exp eg: /b/w+(?=ing/b)
(?<=exp) 自身出现的位置的前面能匹配表达式exp eg: (?<=/pre)/w+/b
(?!=exp) 此位置的后面不能匹配表达式exp eg: /d{3}(?!/d)
(?<!exp) 此位置的前面不能匹配表达式exp eg: (?<![a-z])/d{7}
exp (?<=<(/w+)>).*(?=<///1>)
9、注释:
语法 (?#comment)来包含注释。
eg:2[0-4]/d(?#200-249)|25[0-5](?#250-255)|[01]?/d/d?(?#0-199)
10、贪婪与懒惰匹配:
当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符。考虑这个表达式:a.*b,它将会匹配最长的以a开始,以b结束的字符串。如果用它来搜索aabab的话,它会匹配整个字符串aabab。这被称为贪婪匹配。
有时,我们更需要懒惰匹配,也就是匹配尽可能少的字符。前面给出的限定符都可以被转化为懒惰匹配模式,只要在它后面加上一个问号?。这样.*?就意味着匹配任意数量的重复,但是在能使整个匹配成功的前提下使用最少的重复。现在看看懒惰版的例子吧:
a.*?b匹配最短的,以a开始,以b结束的字符串。如果把它应用于aabab的话,它会匹配aab(第一到第三个字符)和ab(第四到第五个字符)。
代码/语法 | 说明 |
---|---|
*? | 重复任意次,但尽可能少重复 |
+? | 重复1次或更多次,但尽可能少重复 |
?? | 重复0次或1次,但尽可能少重复 |
{n,m}? | 重复n到m次,但尽可能少重复 |
{n,}? | 重复n次以上,但尽可能少重复 |
11、处理选项:
.Net中常用的正则表达式选项:
IgnoreCase
Multiline
Singleline
IgnorePatternWhitespace
RightToLeft
ExplicitCapture
ECMAScript
在C#中,你可以使用Regex(String, RegexOptions)构造函数来设置正则表达式的处理选项。
eg:Regex regex = new Regex("/ba/w{6}/b", RegexOptions.IgnoreCase);
12、平衡组/递归匹配:
语法构造:
- (?'group') 把捕获的内容命名为group,并压入堆栈(Stack)
- (?'-group') 从堆栈上弹出最后压入堆栈的名为group的捕获内容,如果堆栈本来为空,则本分组的匹配失败
- (?(group)yes|no) 如果堆栈上存在以名为group的捕获内容的话,继续匹配yes部分的表达式,否则继续匹配no部分
- (?!) 零宽负向先行断言,由于没有后缀表达式,试图匹配总是失败
< #最外层的左括号 [^<>]* #最外层的左括号后面的不是括号的内容 ( ( (?'Open'<) #碰到了左括号,在黑板上写一个"Open" [^<>]* #匹配左括号后面的不是括号的内容 )+ ( (?'-Open'>) #碰到了右括号,擦掉一个"Open" [^<>]* #匹配右括号后面不是括号的内容 )+ )* (?(Open)(?!)) #在遇到最外层的右括号前面,判断黑板上还有没有没擦掉的"Open";如果还有,则匹配失败 > #最外层的右括号
平衡组的一个最常见的应用就是匹配HTML,下面这个例子可以匹配嵌套的<div>标签:
<div[^>]*>[^<>]*(((?'Open'<div[^>]*>)[^<>]*)+((?'-Open'</div>)[^<>]*)+)*(?(Open)(?!))</div>.