乐趣区

关于正则表达式:ES9ES2018中的正则表达式

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/… 有改变
退出移动版