ES2018 新特征之:正则表达式反向断言

ES2018 新特性

“正则表达式反向断言” 提案 proposal-regexp-lookbehind 由 Gorkem Yakin, Nozomu Katō, Daniel Ehrenberg 负责,目前已经进入 stage 4,预计会是 ES9(ES2018) 的一部分。

1. 概述

断言(Assertion)是一个对当前匹配位置之前或之后的字符的测试, 它不会实际消耗任何字符,所以断言也被称为“非消耗性匹配”或“非获取匹配”。

正则表达式的断言一共有 4 种形式:

零宽正向肯定断言(zero-width positive lookahead assertion)

零宽正向否定断言(zero-width negative lookahead assertion)

零宽反向肯定断言(zero-width positive lookbehind assertion)

零宽反向否定断言(zero-width negative lookbehind assertion)

这里面的 pattern 是一个正则表达式。

lookahead 和 lookbehind 通过被翻译为:

正向 负向

前向 后向

正向 反向

前瞻 后瞻

……

本文档使用“正向”、“反向”。

2. Lookahead assertions 正向断言

在当前的 JavaScript 正则表达式版本中,只支持正向断言。

正向断言的意思是:当前位置后面的字符串应该满足断言,但是并不捕获,仅此而已。

举个例子:

这个正则表达式可以匹配 ,但是正则表达式匹配到的字符串不包含 。(这个正则表达式可以匹配 中的 ,注意,匹配的结果是 ,并不是 )

但是如果这个字符串没有包含 ,那么这个正则表达式无法成功匹配:

如果使用否定断言则正好相反:

3. 反向断言

反向断言和正向断言的行为一样,只是方向相反。

反向肯定断言使用语法 。

比如我们想获取所有的人民币金额,但是不获取其它货币(比如美元):

反向否定断言使用语法 ,和肯定断言正好相反:

在上面的例子中, 的结果是 ,并不是我们认为的 。

这不是反向断言的一个例外,而是这段代码的一个小 bug。

这段正则表达式匹配到了 里面的 。因为 前面是 而不是 ,完全符合反向否定断言规则。

4. 组合

多个断言(任意顺序)可以同时出现。

比如 匹配前面有三个数字但不是 的字符串 。

注意,每个断言独立应用到对目标字符串该点的匹配。首先它会检查前面的三位都是数字,然后检查这三位不是 。 这个模式不能匹配 前面有三位数字然后紧跟 3 位非 共 6 个字符的字符串,比如, 它不匹配 。 匹配 这个字符串的模式可以是 。

这种情况下,第一个断言查看(当前匹配点)前面的 6 个字符,检查前三个是数字, 然后第二个断言检查(当前匹配点)前三个字符不是 。

断言可以以任意复杂度嵌套。

比如 匹配前面有 但是 前面没有 的 。

另外一个模式 则匹配前面有三个数字字符紧跟 3 个不是 的任意字符的 。

5. 细节

5.1 从右向左的贪婪匹配

如果组中有贪婪匹配的子模式,则在反向断言中的捕获组将具有不同的值。

当在反向断言中,右侧的组将捕获大多数字符,而不是左侧的组。

当模式 匹配 时,第 1 个组捕获 ,第 2 个组捕获 。

当普通模式 匹配 时,第 1 个组捕获 ,第 2 个组捕获 。

5.2 捕获组的索引

在反向断言匹配中,组的次序是从左到右的。

当模式 匹配 时, 是 , 是 。

5.3 引用捕获组

只有当捕获组被执行后,我们才能对他进行引用。

例如在正则表达式 中, 的值始终是空字符串,正确的写法是 。

6 实现

V8, shipping in Chrome 62

XS, in January 17, 2018 update

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180326B1533E00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券