正则表达式语法

[TOC]

元字符


































代码 说明
. 匹配除换行符以外的任意字符
\w 匹配字母或数字或下划线或汉字
\s 匹配任意的空白符
\d 匹配数字
\b 匹配单词的开始或结束
^ 匹配字符串的开始
$ 匹配字符串的结束

字符转义

如果想查找元字符本身的话,就需要将字符转义 如:\* \.

重复






























代码 说明
* 重复零次或更多次
+ 重复一次或更多次
? 重复零次或一次
{n} 重复n次
{n,} 重复n次或更多次
{n,m} 重复n到m次

字符类

要想查找数字,字母或数字,空白是很简单的,因为已经有了对应这些字符集合的元字符,但是如果你想匹配没有预定义元字符的字符集合(比如元音字母a,e,i,o,u),应该怎么办?

1
2
3
- [aeiou] 匹配元音字母
- [0-9] 匹配数字范围0-9(与\d含义一致)
- [a-z0-9A-Z_] 匹配字母数字下划线(只考虑英文时,与\w含义一致)

案例1:
匹配几种电话号码:
(010)88886666,或022-22334455,或02912345678

1
\(?0\d{2}[) -]?\d{8}

分枝条件

分枝条件指的是有几种规则,如果满足其中任意一种规则都应该当成匹配,具体方法是用|把不同的规则分隔开。

观察案例1表达式,发现其匹配存有以下缺陷:
能够同时匹配010)12345678或(022-87654321这种不正确的格式.因此,解决这种问题要使用分枝条件,如下:

1
2
3
4
5
6
7
8
- 0\d{2}-\d{8}|0\d{3}-\d{7}  
这个表达式能匹配两种以连字号分隔的电话号码:一种是三位区号,8位本地号(如010-12345678),一种是4位区号,7位本地号(0376-2233445)

- \(0\d{2}\)[- ]?\d{8}|0\d{2}[- ]?\d{8}
这个表达式匹配3位区号的电话号码,其中区号可以用小括号括起来,也可以不用,区号与本地号间可以用连字号或空格间隔,也可以没有间隔。你可以试试用分枝条件把这个表达式扩展成也支持4位区号的。

- \d{5}-\d{4}|\d{5}
这个表达式用于匹配美国的邮政编码。美国邮编的规则是5位数字,或者用连字号间隔的9位数字。

注意: 用分枝条件时,要注意各个条件的顺序,上面例子如果改成\d{5}|\d{5}-\d{4}的话,那么就只会匹配5位的邮编(以及9位邮编的前5位)。原因是匹配分枝条件时,将会从左到右地测试每个条件,如果满足了某个分枝的话,就不会去再管其它的条件了

分组

当想要重复多个字符时,可以使用小括号来指定子表达式(也叫做,分组),然后可以指定子表达式的重复次数.
案例2
匹配ip地址:

1
2
3
4
5
- (\d{1,3}\.){3}\d{1,3} 
简单的ip地址匹配,缺陷是会匹配到256.300.888.999这种不可能存在的IP地址

- ((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)
精确匹配ip地址,由于正则不支持算术比较,所以只能使用冗长的分组和分枝条件

反义

有时需要查找不属于某个能简单定义的字符类的字符。比如想查找除了数字以外,其它任意字符都行的情况,这时需要用到反义






























代码 说明
\W 匹配任意不是字母,数字,下划线,汉字的字符
\S 匹配任意不是空白符的字符
\D 匹配任意非数字的字符
\B 匹配不是单词开头或结束的位置
[^x] 匹配除了x以外的任意字符
[^aeiou] 匹配除了aeiou这几个字母以外的任意字符

后向引用

使用小括号指定一个子表达式后,匹配这个子表达式的文本(也就是此分组捕获的内容)可以在表达式或其它程序中作进一步的处理。默认情况下,每个分组会自动拥有一个组号,规则是:从左向右,以分组的左括号为标志,第一个出现的分组的组号为1,第二个为2,以此类推。

后向引用用于重复搜索前面某个分组匹配的文本。例如,\1代表分组1匹配的文本.
案例3
匹配重复的单词

1
- \b(\w+)\b\s+\1\b 匹配go go或kitty kitty这类单词(\1代表第一个分组)

组名也可以自定义,语法如下:
(?\<name>exp)
案例3变形如下:

1
2
3
- \b(?<Word>\w+)\b\s+\k<Word>\b
注意:\k<name>表示使用定义的别名
后向引用其它用法总结:










































分类 代码/语法 说明
捕获 (exp) 匹配exp,并捕获文本到自动命名的组里
(?<name>exp)
匹配exp,并捕获文本到名称为name的组里,也可以写成(?’name’exp)
(?:exp) 匹配exp,不捕获匹配的文本,也不给此分组分配组号(一般用于只验证规则,不需要捕获内容)
零宽断言 (?=exp) 匹配exp前面的位置
(?<=exp) 匹配exp后面的位置
负向零宽断言 (?!exp) 匹配后面跟的不是exp的位置
(?<!exp) 匹配前面不是exp的位置
注释 (?#comment)
此类型的分组不对正则表达式的处理产生任何影响,用于提供注释让人阅读

贪婪与懒惰

当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符.如:
a.*b,它将会匹配最长的以a开始,以b结束的字符串。如果用它来搜索aabab的话,它会匹配整个字符串aabab。这被称为贪婪匹配
相反,有时需要尽可能少的匹配,称为懒惰匹配,语法是在表达式之后加一个?.同上面表达式变成懒惰匹配 : a.*?b


























代码/语法 说明
*? 重复任意次,但尽可能少重复
+? 重复1次或更多次,但尽可能少重复
?? 重复0次或1次,但尽可能少重复
{n,m}? 重复n到m次,但尽可能少重复
{n,}? 重复n次以上,但尽可能少重复