RegExp Lookbehind Assertions S4
中文标题:正则表达式后行断言
- 阶段: Stage 4
- 状态: 已完成
- ECMAScript 版本: ES2018
- 同步时间: 2026年8月26日
- English original · 官方仓库
该提案为 ECMAScript 正则表达式添加了后行断言,允许模式基于前面的内容进行匹配而不消耗字符。它包含正向后行断言和负向后行断言两种形式,支持无限模式以及反转的匹配顺序。
以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。
正则表达式后行断言
作者:Gorkem Yakin、Nozomu Katō、Daniel Ehrenberg
阶段 4
简介
环视是零宽断言,用于匹配字符串而不消耗任何字符。ECMAScript 已有前向断言(lookahead),但缺少向后匹配的方式,而后行断言(lookbehind)提供了这一能力。通过后行断言,可以确保一个模式前面是否出现另一个模式,例如匹配美元金额而不捕获美元符号。
高级 API
后行断言有两种形式:正向后行断言和负向后行断言。
正向后行断言用 (?<=...) 表示,它确保括号内的模式出现在断言后面的模式之前。例如,如果想匹配美元金额而不捕获美元符号,可以使用 /(?<=\$)\d+(\.\d*)?/,这会匹配 '$10.53' 并返回 '10.53'。然而,它不会匹配 €10.53。
负向后行断言用 (?<!...) 表示,它确保括号内的模式不会出现在断言后面的模式之前。例如,/(?<!\$)\d+(?:\.\d*)/ 不会匹配 '$10.53',但会匹配 '€10.53'。
所有正则表达式模式,甚至是无限重复的模式,都允许作为后行断言的一部分。因此,可以编写 /(?<=\$\d+\.)\d+/ 来匹配美元金额并只捕获小数部分。
通常,模式匹配从最左边的子模式开始,如果左边子模式成功,则向右继续。当在断言中时,匹配顺序会反转。模式从最右边的子模式开始匹配,并向左推进。例如,给定 /(?<=\$\d+\.)\d+/,模式会先找到一个数字,然后确保它前面是 .(向后匹配),接着从 . 开始匹配 \d+,最后从断言内 \d+ 开始的位置匹配 $。由于这个反转,回溯方向也会反转。
细节
在后行断言中,匹配语义是向后进行的——断言内的正则表达式片段被反转,字符串从后向前遍历。这对语义有几个影响。
早期提案是禁止在断言内使用无限重复。Perl 使用这种更受限的语义。然而,如果细节以特定方式确定下来,似乎可以实现支持无限重复的更广泛语义。V8 中已经有采用这种语义的草稿实现。
贪婪性从右到左
首先,如果在断言内的捕获组中包含贪婪量词的子模式,其捕获的值与在断言外时不同。在断言内时,右侧的组捕获最多的字符,而不是左侧的组。例如,给定 /(?<=(\d+)(\d+))$/ 和字符串 '1053',第二个组捕获 '053',第一个组捕获 '1'。而使用 /^(\d+)(\d+)/ 时,第一个组捕获 '105',第二个组捕获 '3'。
捕获组编号
在断言内,捕获组按从左到右的顺序编号。在示例 /(?<=(\d+)(\d+))$/ 匹配字符串 '1053' 时,match[1] 为 "1",match[2] 为 "053"。
引用捕获组
在断言内,只能引用已经求值的捕获组。也就是说,该组必须位于引用的右侧。例如,/(?<=(.)\1)/ 不是很有用的正则表达式,因为 \1 无法解析,会匹配空字符串。相反,要查找前面两个相同字母,可以写 /(?<=\1(.))/。
负向断言
类似于 ECMAScript 正则中长期存在的负向前瞻断言 /(?!.)/,该提案包含负向后行断言 /(?<!.)/。
规范草案
由 Thomas Wood 和 Claude Pache 编写的规范片段。
实现
- V8,在 Chrome 62 中已发布
- XS,在 2018年1月17日更新 中