共计 2452 个字符,预计需要花费 7 分钟才能阅读完成。
ES9 中正则表达式相干次要有两个提案:正则表达式 命名 捕捉组 & 正则表达式 dotAll 模式,目前都已进入 stage4 阶段。
正则表达式命名捕捉组
ECMAScript 提案“正则表达式命名捕捉组”proposal-regexp-named-group 由 Gorkem Yakin, Daniel Ehrenberg 负责。
1. 什么是捕捉组
捕捉组就是把正则表达式中子表达式匹配的内容,保留到内存中以数字编号或显示命名的组里,不便前面援用,且这种援用既能够在正则表达式外部,也能够在正则表达式内部。
捕捉组有两种模式,一种是一般捕捉组,另一种是命名捕捉组。
目前 JavaScript 只反对数字模式的一般捕捉组,而这个提案就是为了给 JavaScript 减少命名捕捉组。
2. 捕捉组编号规定
编号规定指的是以数字为捕捉组进行编号的规定,编号 0 的捕捉组代表正则表达式整体。
const regex = /(\d{4})-(\d{2})-(\d{2})/;
const matchers = regex.exec('2020-12-02');
console.table(matchers)
3. 命名捕捉组
应用数字捕捉组的一个毛病是对于援用不太直观。比方下面的例子,咱们绝对比拟难分分明哪个组代表年,哪个组代表月或者日。而且,当咱们交互了年和月的值时,应用捕捉组援用的代码都须要更改。
而命名捕捉组就是为了解决这个问题。
命名捕捉组能够应用 (?<name>…) 语法给每个组起个名称。因而,用来匹配日期的正则表达式能够写为:
/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/
每个捕捉组的名字必须惟一,否则会抛出异样:
另外,捕捉组的名字必须合乎 JavaScript 命名标准:
命名捕捉组能够通过匹配后果的groups
属性拜访。
let regx = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
let result = regx.exec('2020-12-02');
result.groups.year === '2020';
result.groups.month === '12';
result.groups.day === '02';
result[0] === '2020-12-02';
result[1] === '2020';
result[2] === '12';
result[3] === '02';
应用解构赋值的例子:
let regx = /^(?<one>.*):(?<two>.*)$/;
let {groups: {one, two}} = regx.exec('foo:bar');
console.log(`one: ${one}, two: ${two}`);
4. 反向援用
当须要在正则表达式外面援用命名捕捉组时,应用 \k<name>
语法。
let duplicate = /^(?<half>.*).\k<half>$/;
duplicate.test('a*b'); // false
duplicate.test('a*a'); // true
如果援用一个不存在的命名捕捉组,会抛出异样:
命名捕捉组也能够和一般数字捕捉组一起应用:
let triplicate = /^(?<part>.*).\k<part>.\1$/;
triplicate.test('a*a*a'); // true
triplicate.test('a*a*b'); // false
5. 替换
命名捕捉组也能够在 String.prototype.replace
函数中援用,应用 $<name>
语法。
let regx = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
let result = "2020-12-02".replace(regx, '$<day>/$<month>/$<year>');
console.log(result === '02/12/2020');
String.prototype.replace
第 2 个参数能够承受一个函数。这时,命名捕捉组的援用会作为 groups
参数传递进取。
第 2 个参数的函数签名是function (matched, capture1, ..., captureN, position, S, groups)
。
let regx = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
let result = '2020-12-02'.replace(regx, (...args)=>{let { day, month, year} = args[args.length - 1];
return `${day}/${month}/${year}`
});
result === '02/12/2020';
6. 命名捕捉组未匹配
如果一个 可选 的命名捕捉组没有匹配时,在匹配后果中,此命名组仍然存在,值是undefined
。
let regx = /^(?<optional>\d+)?$/;
let matchers = regx.exec('');
matcher[0] === '';
matchers.groups.optional === undefined;
如果捕捉组不是可选的,匹配后果是null
。
let regx = /^(?<foo>\d+)$/;
let matchers = regx.exec('');
matchers === null;
7. 向下兼容
/(?<name>)/
和 /\k<name>/
只有在命名捕捉组中才有意义。如果正则表达式没有命名捕捉组,那么 /\k<name>/
仅仅是字符串字面量 "k<name>"
而已。
8. 实现
- V8, shipping in Chrome 64
- XS, in January 17, 2018 update
- Transpiler (Babel plugin)
- Safari beginning in Safari Technology Preview 40
正则表达式 dotAll 模式
- 转自 https://esnext.justjavac.com/… 有改变