零宽断言用于确认位置而非匹配内容,分正向/负向先行与后行四种类型,支持上下文精准定位,广泛应用于密码校验、日志过滤和结构化提取等场景。

零宽断言不是“匹配内容”,而是“确认位置”——它不抓取字符,只回答“这里能不能接上某段模式”或“前面有没有某段模式”。这种能力让正则从“找字符串”升级为“按上下文精准定位”,特别适合密码校验、日志过滤、结构化提取等真实场景。
正向先行断言:确保后面有东西,但不拿走
语法 (?=pattern),常用于“必须包含但不捕获”的验证。
- 检查密码是否含数字和大写字母:用
^(?=.*[0-9])(?=.*[A-Z]).{8,}$,两个(?=.*...)并列断言,分别确认数字和大写字母存在,^和$锁定整行,主体.{8,}只管长度 - 提取邮箱用户名(@前部分):用
\b\w+(?=@example\.com),匹配单词,但仅当它紧挨着@example.com时才生效,结果里不含@... - 替换带条件的关键词:比如把 “error” 替成 “ERROR”,但只在后面跟数字时才换,可用
re.sub(r'error(?=[0-9])', 'ERROR', text)
负向先行断言:排除特定后缀,避免误伤
语法 (?!pattern),核心价值是“避开干扰项”。
- 过滤不含 ERROR 的日志行:
^(?!.*ERROR).*$,从行首开始断言:整行不能出现 ERROR,再匹配整行内容 - 匹配非图片扩展名的文件:
\b\w+\.(?!jpg|png|gif)\w{2,4}\b,点号后用(?!jpg|png|gif)拒绝常见图片类型,再继续匹配合法扩展名 - 防止连续重复字符:
^(?!.*(.).\1{2}).*$,断言不存在“任一字符连续出现三次”的情况,适合强密码规则
后行断言:依赖前面内容做判断
包括 (?(正向)和 (?(负向),适用于“已知前缀,只取后面”的提取任务。
- 提取价格数字(只取 $ 后面的数字):
(?,匹配一串数字,但前提是它前面紧挨着 <code>$ - 提取中括号内时间:
(?,前后都用断言框定边界,中间 <code>[^]]+安全匹配非右括号内容 - 跳过注释中的数字:
(?,匹配独立数字,但排除那些前面刚好是 <code>//的情况(如代码注释里的数字)
组合与注意事项
多个断言可叠加使用,但需注意顺序和引擎支持。
- Python、Perl、grep -P 全支持四种断言;JavaScript 不支持后行断言(
(? 和 <code>(?) - 断言本身不占位,所以
a(?=b)c匹配的是 “abc” 中的 a 和 c,b 只是条件,不出现在结果里 - 避免过度嵌套:像
(?=(?=(?=x)))理论可行,但可读性和性能会明显下降,优先拆解逻辑 - 断言位置很关键:写成
\d+(?=px)是匹配“后面是 px 的数字”,而(? 才是匹配“前面是 font-size: 的数字”











