排除性的位置条件
负向先行断言检查右侧不满足某条件:条件不成立时当前位置可用,成立则换位置重试。它表达的是「后面别出现这些内容」,与字符类取反的区别在于前者可以排除整段结构,后者只能排除单个字符。
它同样零宽
被排除的内容不会被消耗,也不会出现在结果里。因此它常用来做纯粹的「这里不该有某物」判断,而不用改动匹配到的文本。
基本信息
| 写法 | 圆括号内以问号感叹号开头,后面写要排除的条件 |
|---|---|
| 宽度 | 零宽,不消耗字符 |
| 与取反字符类的分工 | 排除多字符结构用断言,排除单字符集合用取反字符类 |
| 可叠加 | 与其它断言并排写在同一个位置 |
| 引擎支持 | PCRE、Python、Java、.NET、JavaScript 支持;无回溯引擎通常不支持 |
| 常见搭配 | 行首锚点加负向断言,用来跳过注释行或空行 |
典型使用场景
- 过滤配置文件里的注释行与空行
- 匹配关键字时避免命中更长单词的一部分
- 排除掉特定后缀的标识,例如临时文件
- 要求某段内容后面不能紧跟数字或标点
- 提取字段时避开已保留的关键字
排除写法的常见用法
排除写法的常见用法
^(?!\s*#) 行首之后不是注释符:过滤注释行
\bcat(?!\w) 匹配独立单词 cat,排除 concatenate 之类
^(?!.*\badmin\b) 整行不允许出现 admin 这个词
\d+(?![.\d]) 数字后面不能是点号或数字,用来取整数部分
(?!.*\.tmp$)\S+ 排除以 .tmp 结尾的标识
# 注意:它不消耗字符,所以结果里看不到被排除的内容排除需求的写法选择
| 需求 | 推荐写法 | 原因 |
|---|---|---|
| 排除若干单字符 | 取反字符类 | 更短更快,语义直观 |
| 排除一段结构 | 负向先行断言 | 可取反整段内容 |
| 排除整行含某词 | 行首锚点加负向断言 | 需覆盖整行范围 |
| 排除特定结尾 | 负向断言加串尾锚点 | 结合锚点限定范围 |
负向断言里写点号重复时要留神:检查的是「整个右侧是否存在该结构」,范围过宽会让判断条件难以预测。能用锚点或精确字符类限定范围就不要用点号。
需要判断「整串不含某内容」时,必须把断言放在串首并让内部覆盖整串,否则只能约束断言所在的那一小段位置。