正则表达式 是一种用来描述一定数量文本的模式,通过定义好的正则语句能匹配到目标文本集中所想要的文本。
比如要在文本"her phone number is 111-1111-1111" 中取到电话号码,首先知道电话的格式:1开头加上2个数字加上-加上4个数字加上-加上4个数字。这些规则就可以来写正则表达式了: '/1[\d]{2}-[\d]{4}-[\d]{4}/'。 //的中间就是正则表达式。[]中是字符集\d,表示的是任意数字,而{2}{4}则分别代表匹配前面的字符几次。下面系统地整理下正则表达式的使用方法:
一.字符集
1. []: 字符集:中括号中的是想匹配的字符的集合.
如:/[abc]/的作用相当于匹配a字符或b字符或c字符,与/a|b|c/作用相同,顺便一说,|的意义是或。
[]的后面也可以加上{time},来表示对这字符集匹配time次。
[]中若字符的类型相同,顺序连贯,也可以用'-'符号将首尾连起来。如'/[a-z][a-h][A-Z][0-9]/'代表匹配第一个字符在a到z的26个字母中,第二个字符在a到h的8个字母中,第三个字符是0到9的10个数字中。
2. [^]: 取反字符集:匹配所有不在括号中出现的字符。
如/[^a]/ 匹配所有非a字符。用法可以参考字符集[]的用法,只是效果是取反的。
3. ^ 从文本的开始处匹配 如:'/^abc/' 匹配以abc为开始的文本
4. $ 从文本的结束处匹配 如:'/abc$/' 匹配以abc为结束的文本
二.简化字符集
字符集可以按规律划分为以下几类,使用简化字符集可以提高写正则的效率。
1. \d :数字字符集,匹配数字。 相当于[0-9]
2. \s :任意的空白符 相当于[ ]
3. \w: 数字或子母或下划线。 相当于[0-9a-zA-Z_]
4. . 除换行符以外的任意字符。 相当于[^\n\r]
5. \b 匹配单词的开始或结束 \babc\b 匹配文本'this is abc'中的单词abc
6 \D 任意非数字字符 相当于[^0-9]
7. \S 任意非空白字符 相当于[^ ]
8. \W 任意不是字母数字或下划线的字符
9. \B 任意不是单词的开头或结尾
三.匹配次数
1. + 一次或多次。 如 /a+/ 可以匹配a,aa,aaa,aaaa....
2. * 0次或多次。
3. ? 0次或一次。
4. {n} n次
5. {n,} n次或n次以上
6. {n,m} n到m次
四. 懒惰限制符
1. *? 重复任意次,但尽量少次。 相当于*的最少匹配次数 相当于'/a+?/' 匹配'aaaa'时会匹配出a
2. +? 重复一至多次,尽量少次。 相当于+的最少匹配次数
3. ?? 重复0次到1次,尽量少次。
4. {n,}? 重复n次或n次以上,尽量少次。
5. {n,m}? 重复n到m次,尽量少次。
五.组与向后引用
正则表达式中用()括起来的部分所匹配到的文本会分到单独的组中,若没名字则默认从1开始递增的值为组名,有设置名字的组则以名字为组名(如2所述),而且还能以组名代表式子向后引用:
1. 普通捕获:
'/(exp)\1/' exp表示的是表达式,\1代表的是在xp式子匹配到的文本。
如:'/([\w]{3}).*\1/' 表示是匹配到3个数字或字符或下划线组成的文本,存入组1中,中间匹配任意字符任意次数,后面再匹配组1中的文本,能匹配到的格式是: 'abcdefabc','d_1d_1',组1存的是'abc','d_1',而后面组1又出现了,所以整个文本匹配成功。
2. 命名捕获
'/(?<name>exp)\k<name>/' 也可以写成"/(?'name'exp)\k'name'/" 与上1类似,将捕获的文本保存在组name中。name可以自己命名。
而组的作用是什么呢?PHP中的preg_match_all()方法中可以看到用处:
echo'<pre>'; $str='yes,thatisok!';//文本 $repex='/(?<anser>ok).*\k<anser>/';//正则表达式如果匹配到ok,则分配到anser组中 $count=preg_match_all($repex,$str,$match);//匹配成功次数 var_dump($count);//1 var_dump($match);//匹配结果集:array('0'=>'ok!','anser'=>'ok','1'=>'ok') var_dump($match['anser']);//匹配结果集中的anser组
从结果看到,匹配成功的次数是1次,而且文本组有2个,一个是默认的1,一个是设置的anser.
组的作用还可以引用在替换式中,如PHP中的preg_replace():
$repex='/.*([\w]{3,}\.[\w]+\.[\w]{2,3})/'; $str='link=www.example.com'; $urlTag=preg_replace($repex,"<ahref='\\1'>",$str);//将$str的内容替换成"<ahref='\\1'>",\\1则代表正则中的分组1 var_dump($urlTag);//结果:string'<ahref='www.example.com'>'(length=26)
在这里注意的是""中的引用需要多加一个\则组1变成\\1,而' '号中则还是\1。
3. 不分组不引用式括号
(?:exp) 有些表达式只是需要括号将内容括起来当一个小整体,这时用这种方法括起来就不会产生分组和引用,减少资源的浪费。
4. 零宽断言
(?=exp) 匹配exp表达式前面的内容,即以exp结尾的内容但又不包括exp。
(?<=exp) 匹配exp表达式后面的内容,即以exp开始的内容但又不包括exp。
5. 负向零宽断言
(?!exp) 匹配不是以exp结尾的内容。
(?<!exp) 匹配不是以exp开始的内容。
6. 注释
(?#comment) 括号中的comment对表达式并无影响,只是注释作用。
六. 处理选项
1. i 匹配时不区分字母大小写。 如'/text/i' 能匹配到TeXt
2. m 多行模式 更改^和$的含义, 使它们分别在任意一行的行首和行尾匹配,而不仅仅在字符串的开关和结尾匹配,在此状态下$的含义是匹配\n之前的位置及字符串结束前的位置 。
如 : 用 '/\w$/m' 匹配文本"abc\nabc\n"的匹配结果:c,c .(2次换行前的c都匹配到)。不加m,结果c
3.s 单行模式. 更改'.'的含义,使它与每个字符依次匹配,包括换行符\n(.本来是匹配除换行符以外的文本)
注意:
1. 正则表达式中有特殊字符:( )[ ] \ ^ $ . ? + * | 想匹配这些字符的本体,需要加上\来换码。
2. 正则表达式用单引号与双引号括时有些细节会有差别,双引号括时,引用分组如\1得写成\\1,而单引号则是\1。
3. 字符串中有\n\r\t等特殊字符时,需用双引号。
4. 匹配次数的重叠需谨慎,如'/([\w]{3}){4,6}/' 所代表的是匹配12到18次的\w