正向预查((?=...))和负向预查((?!...))是零宽断言,不消耗字符,仅检查位置前后条件是否满足:前者要求后续能匹配指定模式,后者要求后续不能匹配;常用于密码校验、邮箱提取、URL过滤等场景。

JavaScript 正则中的正向预查((?=...))和负向预查((?!...))属于零宽断言,它们不消耗字符,只检查位置前/后的模式是否满足条件,从而实现“条件约束”——即匹配需以某条件为前提,但该条件本身不参与最终匹配结果。
正向预查:要求后面必须出现某模式
语法:(?=pattern),表示当前位置之后的字符串必须能匹配 pattern,但不包含它。
- 常用于密码强度校验:比如“至少含一个数字且至少8位”可写为
^(?=.*\d).{8,}$。
→(?=.*\d)确保整个字符串中存在数字(任意位置),.{8,}匹配主体;两者叠加实现“有数字”+“长度够”,但数字不被重复计入长度。 - 提取邮箱用户名(@之前部分)但仅限域名是
gmail.com的:^([^\s@]+)(?=@gmail\.com$)
→(?=@gmail\.com$)断言后面紧跟着@gmail.com且到结尾,^([^\s@]+)捕获用户名,不会把@gmail.com拿进去。
负向预查:要求后面不能出现某模式
语法:(?!pattern),表示当前位置之后不能匹配 pattern。
- 匹配不以
https://开头的 URL:^(?!https?:\/\/).+$
→(?!https?:\/\/)排除开头是http://或https://的字符串,其余任意非空行都可匹配。 - 匹配单词中不含连续两个
a的英文单词:\b(?!.*aa)\w+\b
→(?!.*aa)在词首位置断言:整词里不能出现aa;\w+正常匹配字母数字下划线。
组合使用与常见陷阱
多个零宽断言可并列放在开头,顺序无关(因都不消耗字符),但逻辑要自洽。
立即学习“Java免费学习笔记(深入)”;
- 强密码示例(大小写字母 + 数字 + 特殊符号,至少10位):
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*]).{10,}$ - ⚠️ 注意点:
– 预查只看“能否匹配”,不回溯其内部捕获组(如(?=(\d))中的括号在预查内,外部无法引用);
–$在预查中表示“字符串结尾”,不是“行尾”,多行模式下需用\r?\n或m标志配合$;
– 不要误写成(? 或 <code>(?(后行断言),ES2018 才支持,旧环境不可用。
实际调试建议
零宽断言看不见、摸不着,容易写错。推荐:
- 用浏览器控制台或 regex101.com(选 JavaScript 模式)实时查看匹配过程和分组;
- 先单独测试预查部分,例如
/(?=a)b/.test("ab")→true,/(?=a)b/.test("cb")→false; - 避免嵌套预查(如
(?=(?=x))),语义混乱且无必要。


















