正则表达式学习笔记

date: 2016-01-07 22:57:25

本文记录了正则表达式的一些常规语法,和对应的例子。算是对这几天来的学习总结。

1. 常用的元字符
.    匹配除换行符以外的任意字符
\w    匹配字母或数字或下划线
\s    匹配任意的空白符
\d    匹配数字
\b    匹配单词的开始或结束
^    匹配字符串的开始
$    匹配字符串的结束
2. 字符转义
\.
\*
\\
3. 常用的限定符
*    重复零次或更多次
+    重复一次或更多次
?    重复零次或一次
{n}    重复 n 次
{n,}    重复 n 次或更多次
{n,m}    重复 n 到 m 次
4. 分支条件
|  其实就是一种或的关系
5. 实例

例一:
假如我要匹配号码

1
(036)-22334345,036-22334345,(036) 22334345,036 22334345

第一种方法:

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

这种方法能匹配到(036)-22334345 但是也能匹配到(036-22334345 或者036)-22334345 因为在表达式中 ( 和 )后面跟上了?,表示(可以出现,也可以不出现, )可以出现也可以不出现。 但是我的需求是()必须成对出现,或者一个都不出现。

第二种方法:

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

匹配结果:

1
(036)-22334345,036-22334345,(036) 22334345,036 22334345

这里用来 “|”符号,这个其实就是一个分支条件,要么满足前面一种情况,要么满足后面一种情况。前面的写法中,我把第一种方法中的()后面的?都去掉了,这就意味着只能同时匹配到()才能满足条件。 “|”后面一种情况中,我把()都去掉,表示结果中不能出现()。把这两种条件组合起来,就满足了我前面的需求。

例二:
假设我要匹配 12345-1234 或者 12345
我用

1
\d{5}|\d{5}-\d{4}

我永远只能匹配到 12345-1234中的前5位 12345。 这是为什么呢?因为匹配分支条件时,都是从左往右匹配,如果条件满足了,就会结束匹配。因此,应该把表达式写成

1
\d{5}-\d{4}|\d{5}

6.分组

前面讲到了对单个字符的重复次数操作,现在教你如何对多个字符做重复操作。多个字符可以看成是一个带()的子表达式。
例三:

1
(\d{1,3\.}){3}\d{1,3}

匹配结果 255.255.255.215,(\d{1,3.})匹配ip地址的每一项,{3}表示重复三次,\d{1,3}表示匹配最后一项
但是这个表达式是有缺陷的,对ip地址中的每一项大小无法约束,如:555.555.555.555也能匹配上。
优化后的表达式:

1
^((2[0-4]\d|25[0-5]|[01]?\d\d)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d)$

7.反义
1
2
3
4
5
6
\W	匹配任意不是字母,数字,下划线
\S 匹配任意不是空白符的字符
\D 匹配任意非数字的字符
\B 匹配不是单词开头或结束的位置
[^x] 匹配除了x以外的任意字符
[^aeiou] 匹配除了aeiou这几个字母以外的任意字符
8.后向引用

我在分组中捕获的内容,如果在后面还想引用的话,可以使用向后引用的方式。规则如下,每一个分组都会对应一个编号,从左向右 1,2,3…
例如我要匹配255.255.255.255,改造如下:

1
(2[0-4]\d|25[0-5]|[01]?\d\d)\.(\1)\.(\1)\.(\1)

(\1)会自动引用第一次匹配到的结果

9.零宽断言
1
2
3
4
5
6
7
8
(?=exp)
零宽度正预测先行断言,它断言自身出现的位置的后面能匹配表达式 exp,如\d{3}(?=度) 能匹配 360度,但是结果不包含“度”
(?<=exp)
零宽度正回顾后发断言,它断言自身出现的位置的前面能匹配表达式 exp, 如(?<=src=\")\w+ 能匹配结果src="http 但不包含src=
(?!exp)
断言此位置的后面不能匹配表达式 exp,其实就是第一种表达式的逆情况,\d{3}(?!度) 能匹配除了“度”结尾的任何情况
(?<!exp)
零宽度负回顾后发断言来断言此位置的前面不能匹配表达式exp, 第二种表达式的逆情况,(?<!src=\")\w+ 能匹配以src="开头的任何情况。

例四:
匹配html中的图片链接:

1
(?<=img(.*?)(src="))[\s|\S][^"]*(?=")

文本内容:

1
<img dsd src="http://k.sinaimg.cn/www/qc/photo_auto/photo/37/72/62143772/62143772_950.jpg/w580h386t50ee6.jpg" alt="一分钟 体验全新Passat B8 Variant">

匹配结果:

1
http://k.sinaimg.cn/www/qc/photo_auto/photo/37/72/62143772/62143772_950.jpg/w580h386t50ee6.jpg

10.注释
1
(?#comment)
11. 贪婪与懒惰

通常我们在匹配的时候会遇到下面两种情况, abababab, 当我需要匹配a.*b的时候, 到底是匹配到ab呢,还是匹配到abababab?
如果是第一种,则称之为懒惰匹配。 如果是第二种情况,则称之为贪婪匹配。
通常正则表达式在匹配的过程中会采取贪婪的匹配模式,因此当我们需要采取懒惰匹配模式的时候,可以使用下面几种限定符:

1
2
3
4
5
*?		重复任意次,但尽可能少重复
+? 重复1此或更多次,但尽可能少重复
?? 重复0此或1次,但尽可能少重复
{n.m}? 重复nm次,但尽可能少重复
{n,}? 重复n此以上,但尽可能少重复