最大最小匹配、零宽断言、反向引用、非获取匹配等
最大、最小匹配
正则表达式中包含能接受重复的限定符时,通常的行为是匹配尽可能多的字符,例如:
用 <.*> 匹配 <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]+$ |