正则表达式先行断言与后行断言
断言(Assertion)不消耗字符,只检查某个位置的前后是否符合条件。
四种断言
| 语法 | 名称 | 含义 |
|---|---|---|
(?=pattern) | 正先行断言 | 后面必须是 pattern |
(?!pattern) | 负先行断言 | 后面不能是 pattern |
(?<=pattern) | 正后行断言 | 前面必须是 pattern |
(?<!pattern) | 负后行断言 | 前面不能是 pattern |
零宽 (zero-width):断言只匹配位置,不消耗字符。
实例讲解
正先行断言 (?=pattern)
匹配后面跟着 pattern 的位置。
regex
\d+(?=元)| 输入 | 匹配 |
|---|---|
价格是128元 | 128 |
总计99件 | 不匹配 |
负先行断言 (?!pattern)
匹配后面不是 pattern 的位置。
regex
\d+(?!元)| 输入 | 匹配 |
|---|---|
价格是128元 | 12(只匹配不后跟"元"的数字部分) |
正后行断言 (?<=pattern)
匹配前面是 pattern 的位置。
regex
(?<=¥)\d+| 输入 | 匹配 |
|---|---|
¥128 | 128 |
$99 | 不匹配 |
负后行断言 (?<!pattern)
匹配前面不是 pattern 的位置。
regex
(?<!¥)\d+| 输入 | 匹配 |
|---|---|
¥128 | 28 |
$99 | 99 |
实战案例
1. 密码复杂度校验
regex
^(?=.*[A-Z])(?=.*[a-z])(?=.*\d).{8,}$(?=.*[A-Z])— 至少一个大写字母(?=.*[a-z])— 至少一个小写字母(?=.*\d)— 至少一个数字.{8,}— 至少 8 个字符
2. 提取 Markdown 链接中的 URL
regex
(?<=\]\().*?(?=\))markdown
[百度](https://www.baidu.com)
[谷歌](https://www.google.com)匹配结果:https://www.baidu.com、https://www.google.com
3. 数字千分位格式化
regex
(?!^)(?=(\d{3})+$)javascript
'12345678'.replace(/(?!^)(?=(\d{3})+$)/g, ',')
// → '12,345,678'注意事项
- JavaScript 支持全部四种断言(ES2018 起支持后行断言)
- Python 的后行断言要求模式宽度固定(不能使用
*、+、{n,}等不定量词) - Go 的
regexp包不支持后行断言,需要使用 RE2 兼容写法