ES6学习笔记之正则表达式的扩展

Learning Card

ES6中的正则表达式有这样一些改变:

  • RegExp构造函数的写法有了更新
    • 可以是正则表达式+修饰符
  • 新的修饰符
    • u修饰符 Unicode模式
    • y修饰符 “粘连”修饰符
  • 新的属性
    • unicode属性 判断是否设置了u修饰符
    • sticky属性 判断是否设置了y修饰符
    • flags属性 返回正则表达式的修饰符
  • 新规则
    • 后行断言
      • 先行断言写法 /x(?=y)/
      • 先行否定断言写法 /x(?!y)/
      • 后行断言写法 /(?<=y)x/
      • 后行否定断言写法 /(?<!y)x/
    • 具名组匹配 给分组添加名字

RegExp构造函数

ES5中RegExp构造函数写法

1
2
3
4
5
// 写法1 参数:字符串 + 修饰符
let regex = new RegExp('xyz', 'i');

//写法2 参数:正则表达式
let regex = new RegExp(/xyz/i);

不允许参数:正则表达式+修饰符的形式,否则会报错

1
let regex = new RegExp(/xyz/, 'i');  //Uncaught TypeError

ES6写法

参数可以是正则表达式 + 修饰符,且新指定的修饰符会覆盖原修饰符

1
new RegExp(/abc/ig, 'i').flags    // "i"

新的修饰符

u修饰符

u修饰符指”Unicode模式”,用于正确处理大于\uFFFF的Unicode字符。

y修饰符

y修饰符叫做”粘连“(sticky)修饰符。

它和g修饰符类似,也是全局匹配,但是后一次匹配必须从上一次匹配成功的下一个位置开始。

1
2
3
4
5
6
7
8
9
let str = 'aaa_aa_a';
let r1 = /a+/g;
let r2 = /a+/y;

r1.exec(str) //['aaa']
r2.exec(str) //['aaa']

r1.exec(str) //['aa']
r2.exec(str) //null

新的属性

unicode属性

unicode属性表示是否设置了u修饰符

1
2
3
4
5
const r1 = /hello/;
const r2 = /hello/u;

r1.unicode //false
r2.unicode //true

sticky属性

sticky属性表示是否设置了y修饰符

1
2
let r = /hello\d/y;
r.sticky //true

flags属性

flags属性会返回正则表达式的修饰符

1
2
3
4
5
//ES5的 source 属性会返回正则表达式的正文
/abc/ig.source //"abc"

//ES6的 flags 属性会返回正则表达式的修饰符
/abc/ig.flags //"gi"

新规则

后行断言

JavaScript原本只支持先行断言和先行否定断言。ES2018引入后行断言。

先行断言指,只有xy前面才匹配,写成**/x(?=y)/,比如匹配百分号之前的数字,写成/\d(?=%)/,先行否定断言指石油x不在y前面才匹配,写成/x(?!y)/**。这两个规则在正则表达式这一节中提到过。

后行断言与先行断言相反,只有xy后面才匹配,写成**/(?<=y)x/,比如只匹配没有符号之后的数字,要写成/(?<=\$)\d+/。同样地,后行否定断言只有x不在y后面才匹配,写成/(?<!y)x/**。

断言 否定断言
先行 /x(?=y)/ /x(?!y)/
后行 /(?<=y)x/ /(?<!y)x/

具名组匹配

正则表达式中使用圆括号进行组匹配,并将匹配结果分别提取出来,但是每一组的匹配含义并不清晰,只能通过序号来引用。

1
2
3
4
5
6
7
8
9
const RE_DATE = /(\d{4})-(\d{2})-(\d{2})/;

const matchObj = RE_DATE.exec('1999-12-31');
const year = matchObj[1]; //1999
const month = matchObj[2]; //12
const day = matchObj[3]; //31

//matchObj ['1999-12-31', '1999', '12', '31', index:0, input: '1999-12-31', groups: undefined]

ES2018引入了具名组匹配(Named Capture Groups),允许为每一个组匹配指定一个名字。

1
2
3
4
5
6
7
8
const RE_DATE = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;

const matchObj = RE_DATE.exec('1999-12-31');
const year = matchObj.groups.year; //1999
const month = matchObj.groups.month; //12
const day = matchObj.groups.day; //31

//matchObj ['1999-12-31', '1999', '12', '31', index:0, input: '1999-12-31', groups: {year: '1999', month: '12', day: '31'}]

ES6学习笔记的内容主要基于阮一峰老师的《ECMAScript 6入门》,原文请见链接