最大最小匹配、零宽断言、反向引用、非获取匹配等
最大、最小匹配
正则表达式中包含能接受重复的限定符时,通常的行为是匹配尽可能多的字符,例如:
用 <.*>
匹配 <h1>People's Daily Online</h1>
匹配结果
共找到 1 处匹配:
<h1>People's Daily Online</h1>
当匹配到 h1 后面的 > 后,还会继续尝试往后匹配,直到匹配到最后一个 >(如果存在的话),若只想匹配到第一个 > 就停止匹配的话,即匹配尖括号里 h1 或 /h1 的话,需设定为最小匹配,方法是在限定符后面加个 ?
:
<.*>
→ <.*?>
匹配结果
共找到 2 处匹配:
<h1>
</h1>
再举个例子
用 a.*b
匹配 aabbccbb
,匹配结果
共找到 1 处匹配:
aabbccbb
用 a.*?b
匹配 aabbccbb
,匹配结果
共找到 1 处匹配:
aab
总结如下:
代码/语法 | 说明 |
---|---|
*? | 重复任意次,但尽可能少重复 |
+? | 重复1次或更多次,但尽可能少重复 |
?? | 重复0次或1次,但尽可能少重复 |
{n,m}? | 重复n到m次,但尽可能少重复 |
{n,}? | 重复n次以上,但尽可能少重复 |
零宽断言
零宽断言是一种零宽度的匹配,它匹配到的内容不会保存到匹配结果中去。简单来说就是给表达式添加一个限定条件,规定表达式前面或者后面需要满足某种条件。
(?=Exp): 后面匹配Exp
(?!Exp): 后面不匹配Exp
(?<=Exp): 前面匹配Exp
(?<!Exp): 前面不匹配Exp
举例字符串 AbcabC
用 (?<=[A-Z])b
匹配
共找到 1 处匹配:
b
用 b(?=[A-Z])
匹配
共找到 1 处匹配:
b
反向引用
将捕获组(圆括号里的表达式)捕获到的内容在正则表达式内部进行引用
在 aabbcccdd
中,如果想匹配连续三个一样的字母,就用到了反向引用
用 ([a-z])\1{2}
匹配,结果
共找到 1 处匹配:
ccc
来拆解一下这个正则
([a-z])
是第一个捕获组
\1
表示引用了第1个捕获组
{2}
表示 \1
重复两次
过程是一开始匹配到了 a
时, \1
就变成了 a
, 然后去匹配 aaa
失败,b
同理,最后只有 ccc
符合
捕获组还可以进行命名,命名规则是 (?<name>)
,使用的时候\k<name>
那么可以给 ([a-z])\1{2}
命名成 (?<char>[a-z])\k<char>{2}
非获取匹配
因为小括号()
会被当做捕获组,有些情况下我们其实不需要它被捕获,则需要添加 ?:
用 (?:[a-z])\1{2}
匹配 aabbcccdd
,结果
(没有匹配)
在括号内加了 ?:
以后,\1
就没有可以引用的了
常用正则表达式
场景 | 正则 |
---|---|
十六进制值 | ^#?([a-f0-9]{6}|[a-f0-9]{3})$ |
电子邮箱 | ^([a-z0-9_.-]+)@([\da-z.-]+).([a-z.]{2,6})$/ /^[a-z\d]+(.[a-z\d]+)*@(\da-z?)+(.{1,2}[a-z]+)+$ |
URL | ^(https?:\/\/)?([\da-z.-]+).([a-z.]{2,6})([\/\w .-])\/?$ |
IP 地址 | ((2[0-4]\d|25[0-5]|[01]?\d\d?).){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)/ /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$ |
Unicode编码中的汉字范围 | ^[\u2E80-\u9FFF]+$ |