ES6 学习(5) ---正则的扩展

正则

正则表达式的声明

 

 1 var regex = new RegExp('xyz', 'i');  // 第一个参数是字符串,第二个参数表示正则表达式的修饰符
 2  // 等价于
 3 var regex = /xyz/i;
 4 
 5  6 
 7 var regex = new RegExp(/xyz/i); // 参数是一个正则表达式,返回一个正则表达式的拷贝
 8 
 9 // 等价于
10 var regex = /xyz/i;

 

在ES6中,RegExp构造器函数第一个是正则对象,第二个参数可以是指定修饰符,而这在ES5中是不允许的,会报错;

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

在这个表达式中,第二个参数修饰符i会覆盖原有正则对象的修饰符ig


 

字符串的正则方法

  字符串对象共有4个方法,可以使用正则表达式: match(), replace(), search() 和 split()

  ES6将这4个方法,在语言内部全部调用RegExp的实例方法,从而做到所有与正则相关的方法,全都定义在RegExp对象上

 

1 // String.prototype.match 调用 RegExp.prototype[Symbol.match]
2 // String.prototype.replace 调用 RegExp.prototype[Symbol.replace]
3 // String.prototype.search 调用 RegExp.prototype[Symbol.search]
4 // String.prototype.split 调用 RegExp.prototype[Symbol.split]

 


 

u修饰符

  ES6 对正则表达式添加了u修饰符,含义为"Unicode 模式",用来正确处理大于\uFFFF的Unicode字符,也就是说,会正确处理四个字节的UTF-16 编码

 

 


 

RegExp.prototype.unicode属性

   正则实例对象新增unicode属性,表示是否设置u修饰符

1 const r1 = /hello/;
2 const r2 = /hello/u;
3 
4 r1.unicode // false
5 r2.unicode // true

 

  上面代码中,可以用unicode来判断是否设置了u修饰符


 

y修饰符

  除了u修饰符,ES6还为正则表达式添加了y修饰符,叫做"粘连"(sticky)修饰符

  y修饰符的作用于g修饰符类似,也是全局匹配,后一次匹配都从上一次匹配成功的下一个位置开始,不同之处在于,g修饰符只要剩余位置中存在匹配就可,而y修饰符确保匹配必须从剩余的第一个位置开始,这也就是"粘连"的含义

1 var s = 'aaa_aa_a';
2 var r1 = /a+/g;
3 var r2 = /a+/y;
4 
5 r1.exec(s) // ["aaa"]
6 r2.exec(s) // ["aaa"]
7 
8 r1.exec(s) // ["aa"]     // 会从_aa_a,中的a开始匹配, g修饰符没有位置要求
9 r2.exec(s) // null        // 会从 _aa_a,中的 _ 匹配,因此会返回null, y修饰符必须从头部开始

 

RegExp.prototype.sticky属性

  与y修饰符相匹配,用来判断正则对象是否设置了y修饰符

var r = /hello\d/y;

r.sticky // true // 判断是否使用y修饰符

 

RegExp.prototype.flags属性

  ES6 为正则表达式新增了flags属性,会返回正则表达式的修饰符

1 // ES5 的 source 属性
2 // 返回正则表达式的正文
3 /abc/ig.source
4 // "abc"
5 
6 // ES6 的 flags 属性
7 // 返回正则表达式的修饰符
8 /abc/ig.flags
9 // 'gi'

 

s修饰符: dotAll模式

  点(.)元字符,可以代表任意单个字符,但是有两个例外,一个是四字节的UTF-16,这个可以使用u修饰符解决,另一个是行终止符(该字符表示一行的终结 \n \r等) 

  /foo.bar/.test('foo\nbar') // false
  /foo.bar/s.test('foo\nbar') // true

  ES2018中引入s修饰符,使得.可以匹配任意单个字符,这被称为dotAll模式,即点(dot)代表一切字符,所以正则表达式还引入了一个dotAll属性,返回一个布尔值,表示该正则表达式是否处在dotAll模式

1 const re = /foo.bar/s;
2 // 另一种写法
3 // const re = new RegExp('foo.bar', 's');
4 
5 re.test('foo\nbar') // true
6 re.dotAll // true
7 re.flags // 's'

 


 

 

具名组匹配

  正则表达式使用圆括号进行组匹配 

1 const RE_DATE = /(\d{4})-(\d{2})-(\d{2})/;
2 
3 const matchObj = RE_DATE.exec('1999-12-31');
4 const year = matchObj[1]; // 1999
5 const month = matchObj[2]; // 12
6 const day = matchObj[3]; // 31

   ES2018 引入了具名组匹配(Named Capture Groups),允许为每一个组匹配指定一个名字,既便于阅读代码,又便于引用。

1 const RE_DATE = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
2 
3 const matchObj = RE_DATE.exec('1999-12-31');
4 const year = matchObj.groups.year; // 1999
5 const month = matchObj.groups.month; // 12
6 const day = matchObj.groups.day; // 31

  如果具名组没有匹配到则该组的值为undefined;

  上面 ?<year> 相当于给每个组加了一个变量名,因此,也可以使用解构赋值

  即: let { groups: { one, two }} = /^( ?<one>.* ):( ?<two>.*)$/u.exec("foo:bar");   

  当字符串替换时,使用$<组名>引用具名组。

1 let re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;
2 
3 '2015-01-02'.replace(re, '$<day>/$<month>/$<year>')
4 // '02/01/2015' 注意: replace的第二参数为字符串

  在正则表达式中还可以引用某个具名组匹配

 1 const RE = /^(?<word>[a-z]+)!\k<word>$/;
 2 RE.test('abc!abc') // true
 3 RE.test('abc!ab') // false
 4 
 5 // 数字引用(\1)依然有效。
 6 const RE_TWICE = /^(?<word>[a-z]+)!\1$/;
 7 RE_TWICE.test('abc!abc') // true
 8 RE_TWICE.test('abc!ab') // false
 9 
10 // 同是还能两者一起用
11 const RE1= /^(?<word>[a-z]+)!\k<word>!\1$/;
12 RE1.test('abc!abc!abc') // true
13 RE1.test('abc!abc!ab') // false

 

String.prototype.matchAll

   一般来说,正则表达式在字符串.match方法中每次只能匹配到一个,但是 matchAll 一次性可以将所有的匹配项全部取出 返回一个伪数组; 之后可以用 ... 或 Array.from() 在转换成数组

 

 

 

———— 不生产代码,只是代码的搬用工

 

posted @ 2020-03-11 23:02  newtt  阅读(138)  评论(0编辑  收藏  举报