零宽意味着什么
零宽说的是断言只判断位置是否满足条件,不移动匹配指针,也不贡献任何字符。因此它既能出现在结果的任何边界上,也不会让匹配片段变长——同样一段文本,加不加断言,匹配到的内容相同,只是通过与否不同。
由此带来的三个推论
第一,断言可以并排叠加,形成「与」关系;第二,断言可以出现在模式开头或结尾,用于约束片段之外的上下文;第三,在替换操作里,零宽位置本身也能成为插入点。
基本信息
| 是否消耗字符 | 不消耗,位置不前进 |
|---|---|
| 是否进入结果 | 不进入,结果里看不到被检查的内容 |
| 可否叠加 | 可并排写在同一位置,多个条件同时成立 |
| 可否包含分组 | 部分引擎允许,内部分组会占用组编号 |
| 与锚点关系 | 锚点本质上也是零宽断言,只是判断的是边界 |
| 失败时行为 | 当前位置不成立,模式从下一个位置继续尝试 |
典型使用场景
- 在替换中插入内容而不改变被匹配的文本
- 提取某符号之后的内容而不把符号纳入结果
- 对同一位置施加多条约束,例如多重格式要求
- 约束片段前后的上下文,判断该片段是否应被选中
- 把长模式拆成「条件断言加实际匹配」两段,便于阅读
零宽带来的行为差异
零宽带来的行为差异
\d+(?=px) 匹配结果只有数字,单位 px 不在结果里
(?<=\$)\d+ 结果只有数字,货币符号不在结果里
(?=.*\d)(?=.*[a-z]) 同一位置叠加两个条件(与关系)
# 替换场景:零宽位置可作为插入点
在每行末尾插入标记:行尾锚点即零宽位置
在数字前插入单位:用先行断言定位数字起始位置
# 对照:消耗字符的写法会把额外内容并入结果
\d+px 结果包含单位,替换时需自行去掉零宽与消耗对照
| 写法类型 | 是否消耗 | 是否出现在结果 | 典型用途 |
|---|---|---|---|
| 先行断言 | 否 | 否 | 约束右侧上下文 |
| 后行断言 | 否 | 否 | 约束左侧上下文 |
| 锚点 | 否 | 否 | 约束首尾位置 |
| 普通分组 | 是 | 是 | 取值与替换 |
| 取反字符类 | 是 | 是 | 排除单字符 |
零宽结构可能产生空匹配,配合替换会插入内容、配合批量查找会得到空结果。写涉及断言的替换逻辑前,先确认输出结果符合预期。
把断言理解成「位置上的条件」而不是「匹配某段内容」,是读懂复杂模式的关键。看到一组并排的断言时,读法应是「这里必须同时满足这些条件」。