引言
正则表达式regular expression
就是一个字符串
来描述一个特征,然后去验证另一个字符串
是否符合这个特征
正则表达式功能
验证
查找
替换
字符
普通字符
字母,数字,汉字,下划线,没有被特殊定义的符号都是普通字符
表达式c
在匹配字符串abcde
时,匹配结果为成功,匹配到的内容为c
,匹配到的位置是,开始于2结束于3
表达式bcd
在匹配字符串abcde
时,匹配结果为成功,匹配到的内容为bcd
,匹配到的位置是,开始于1结束于4
特殊字符
^
匹配输入字符串开始的位置$
匹配输入字符串的结尾位置()
标记子表达式开始和结束位置.
匹配非换行符*
匹配子表达式0次|n次+
匹配子表达式1次|n次?
匹配子表达式0次|1次[]
用来自定义能够匹配多种字符的表达式\
转义{}
修饰匹配次数的符号|
或
空白字符
一些不便于书写的字符采用前面加\
的方法
\f
匹配换页符\n
匹配换行符\r
匹配回车符\t
匹配制表符\v
匹配垂直制表符
转义字符
一些有特殊用法的符号在前面加\
表示符号本身而非特殊意义
\^
\$
\.
\xXX&\uXXXX
表达式中可以使用\xXX
和\uXXXX
表示一个字符X表示一个十六进制数
\xXX
字符范围为0-255
,比如空格
\x20
\uXXXX
可以表示任何字符,比如中
\u4E2D
一般规则
多种字符匹配
默认
与多种字符的匹配指的是与多种字符其中任意一个字符匹配,只能是一个而非多个
\d
匹配一个数字字符[0-9]
\w
匹配一个字母|数字|下划线[A-Za-z0-9_]
\s
匹配一个空白字符[\f\n\r\t\v]
.
匹配除换行符\n
以外的任意一个字符
在表达式\s
\d
\w
\b
表示特殊意义的同时,对应的大写字母表示相反的意义
\S
匹配所有非空白字符\D
匹配所有的非数字字符\W
匹配所有的字母|数字|下划线以外的字符\B
匹配非单词边界即左右两边都是\w
范围或者左右两边都不是\w
范围时的字符缝隙
自定义
使用[ ]
包含多种字符能够匹配到其中任意一个字符
使用[^ ]
包含多种字符能够匹配到其中字符之外的任意一个字符
[ABC]
匹配单个字母A|B|C[^ABC]
匹配除了A|B|C以外的所有字符[A-Z]
匹配所有大写字母[a-z]
匹配所有小写字母[A-Za-z0-9_]
匹配大小写字母|数字|下划线
匹配次数
{n}
匹配n次{n,}
至少匹配n次{n,m}
至少匹配n次,至多匹配m次*
匹配子表达式0次|n次<=>{0,}
+
匹配子表达式1次|n次<=>{1,}
?
匹配子表达式0次|1次<=>{0,1}
定位
^
匹配输入字符串开始的位置不匹配任何字符$
匹配输入字符串的结尾位置不匹配任何字符\b
匹配单词边界\babc
匹配以abc开头的单词,abc\b
匹配以abc结尾的单词
\b
与^
和$
类似,本身不匹配任何字符,但是它要求它在匹配结果中所处位置的左右两边其中一边是\w
范围,另一边是非\w
的范围
表达式内部关系
|
左右表达式之间或
的关系,匹配左边或者右边()
在被修饰匹配次数时,括号中的表达式可以作为整体被修饰
(go\s*)+
匹配let's go go go
匹配结果是go go go
在取匹配结果时,括号中的表达式匹配到的内容可以单独得到
¥(\d+\.?\d*)
匹配$10.9,¥66.9
匹配到的内容为¥66.9
,单独获得括号范围匹配到的内容为66.9
高级规则
贪婪&勉强
贪婪
在使用修饰匹配次数的特殊符号时,有几种表示方法可以使同一个表达式能够匹配不同的次数
比如{m,n}
{m,}
?
*
+
具体匹配的次数随被匹配的字符串而定
这种重复匹配不定次数的表达式,在匹配过程中总是在整个表达式能成功匹配的前提下,尽可能多的匹配字符
针对文本dxxxdxxxd
表达式(d)(\w+)
中(\w+)
匹配到的字符为xxxdxxxd
而非xxx
表达式(d)(\w+)(d)
中(\w+)
匹配到的字符为xxxdxxx
没有匹配到最后一d
是为了让表达式能够匹配成功
同理{m,n}
{m,}
,*
也都尽可能多的匹配,?
在可匹可不匹时也是选择匹,这种匹配原则就叫做贪婪
勉强
在修饰匹配次数的特殊符号后再加上一个?
可以使匹配次数不定的表达式尽可能少的匹配,使可匹可不匹的表达式不匹配,这种匹配模式叫做非贪婪模式
,也叫做勉强
模式
针对文本dxxxdxxxd
表达式(d)(\w+?)
中,(\w+?)
匹配到的字符为x
而非xxx
|xxxdxxxd
表达式(d)(\w+?)(d)
中,(\w+)
匹配到的字符为xxx
而非xxxdxxx
针对文本<td><p>aa</p></td> <td><p>bb</p></td>
表达式<td>(.*)</td>
匹配的结果为<td><p>aa</p></td> <td><p>bb</p></td>
表达式<td>(.*?)</td>
匹配结果为<td><p>aa</p></td>
,在匹配下一次时可以匹配到<td><p>bb</p></td>
反向引用
(xxxxx)
表达式在进行匹配时,表达式引擎会将小括号()
包含的表达式所匹配到的字符串记录下来
实际场景中,当用某种边界来查找,而所需要的内容又不包含边界时,必须使用小括号来指定所要的范围
()
内所匹配的字符串不仅是匹配结束后可以使用,匹配过程中也可以使用
表达式后部可以引用前面()
内匹配的字符串,引用方法是\
加上一个数字,\1
引用第一对括号内匹配到的字符串,\2
引用第一对括号内匹配到的字符串,以此类推
如果一对()
内包含另一对()
,则外层括号先排序号
表达式('|")(.*?)(\1)
匹配'hello',"world"
匹配结果是'hello'
再次匹配的结果是"world"
表达式(\w)\1{4,}
匹配aa bbbb abcdefg ccccc 111121111 999999999
匹配结果是ccccc
再次匹配结果是999999999
这个表达式匹配至少五个连续重复的字符 注意与\w{5,}
不同
表达式<(\w+)\s*(\w+(=('|").*?\4)?\s*)*>.*?</\1>
在匹配<td id='td1' style="bgcolor:white"></td>
匹配结果是Group1td
,Group2id='td1'|style="bgcolor:white"
,Group3='td1'|="bgcolor:white"
,Group4'|"
(?:xxxxx)
括号( )
内的子表达式,如果希望匹配结果不进行记录供以后使用,可以使用(?:xxxxx)
表达式(?:(\w)\1)+
匹配a bbccdd efg
匹配的结果是bbccdd
(?:xxx)
范围的匹配结果不进行记录,因此(\w)
使用\1
来引用
预搜索
正向(右侧)预搜索
^
$
\b
它们都有一个共同点,它们本身不匹配任何字符,只是对字符串的两头或者字符之间的缝隙附加了一个条件
(?=xxxxx)
表达式(?=xxxxx)
在被匹配的字符串中,它对所处的缝隙或者两头附加条件为,所在缝隙的右侧必须能够匹配上xxxxx
这部分的表达式只是作为这个缝隙上附加的条件,并不影响后边的表达式去匹配缝隙之后的字符
表达式Windows (?=NT|XP)
匹配Windows 98 Windows NT Windows 2000
只匹配Windows XP
的Windows
表达式(\w)((?=\1\1\1)(\1))+
匹配aaa ffffff 999999999
匹配前四个f
和前七个9
表达式的意思是匹配一个字符,后面紧跟着至少三个相同的字符,匹配其剩下最后2位之前的部分
(?!xxxxx)
表达式(?!xxxxx)
所在缝隙的右侧,必须不能匹配xxxxx
这部分表达式
表达式((?!\bstop\b).)+
在匹配fdjka ljfdl stop fjdsla fdj
时,将从头一直匹配到stop
之前的位置,如果字符串中没有stop
则匹配整个字符串
表达式do(?!\w)
在匹配字符串done, do, dog
时只能匹配do
反向(左侧)预搜索
(?<=xxxxx)&(?<!xxxxx)"
这两种格式的概念和正向预搜索是类似的,反向预搜索要求的条件是,所在缝隙的左侧
表达式(?<=\d{4})\d+(?=\d{4})
在匹配1234567890123456
时,将匹配除了前4个数字和后4个数字之外的中间8个数字
表达式属性
Ignorecase
默认情况下表达式中的字母区分大小写
配置为I
gnorecase,可使匹配时不区分大小写
有的表达式引擎把大小写概念延伸至UNICODE范围的大小写
Singleline
默认情况下.
匹配除了换行符\n
以外的字符
配置为S
ingleline可使.
匹配包括换行符在内的所有字符
Multiline
文本如下①xxxxxxxxx②\n③xxxxxxxxx④
①②③④表示位置
默认情况下表达式^
和$
只匹配字符串的开始①和结尾④位置
配置为M
ultiline可以使^
匹配①外,还可以匹配换行符之后,下一行开始前③的位置,使$
匹配④外,还可以匹配换行符之前一行结束②的位置
Global
主要在将表达式用来替换时起作用
配置为G
lobal表示替换所有的匹配
一些tips
如果要求表达式所匹配的内容是整个字符串而不是从字符串中找一部分,那么可以在表达式的首尾使用
^
和$
比如^\d+$
要求整个字符串只有数字如果要求表达式所匹配的内容是一个完整的单词而不会是单词的一部分,那么可以在表达式首尾使用
\b
比如\b(if|while|else|void|int……)\b
匹配程序中的关键字表达式不要匹配空字符串否则会一直得到匹配成功而结果什么都没有匹配到
比如准备写一个匹配123
123.
123.5
.5
这几种形式的表达式
整数|小数点|小数数字都可以省略,但是不要将表达式写成\d*\.?\d*
因为如果什么都没有,这个表达式也可以匹配成功
更好的写法是\d+\.?\d*|\.\d+
|
的左右两边对某个字符最好只有一边可以匹配,这样不会因为|
两边的表达式因为交换位置而有所不同能匹配空字符串的子匹配不要循环无限次
如果括号内的子表达式中的每一部分都可以匹配0次,而这个括号整体又可以匹配无限次,那么情况可能比上一条所说的更严重,匹配过程中可能死循环
虽然现在有些正则表达式引擎已经通过办法避免了这种情况出现死循环了,但是仍然应该尽量避免出现这种情况
如果在写表达式时遇到了死循环,也可以从这一点入手,查找一下是否是上述原因