ES6(五)正则的扩展


RegExp 构造函数

var regex = new RegExp('xyz', 'i');
// 等价于
var regex = /xyz/i;
var regex = new RegExp(/xyz/i); 
// 注意 ES5 不允许在给定一个正则表达式后,
// 像上面一样继续添加修饰符,会报错
// ES6 则改变了这种行为,可以使用第二个参数来指定修饰符
// 返回的正则表达式会忽略原有的正则表达式的修饰符,指定参数所给的修饰符
// 等价于
var regex = /xyz/i;

参数既可以为字符串,也可以为一个正则表达式


字符串的正则方法

ES6 出现之前,字符串对象共有4个方法,可以使用正则表达式

  • match()
  • replace()
  • search()
  • split()

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

  • RegExp.prototype[Symbol.match]
  • RegExp.prototype[Symbol.replace]
  • RegExp.prototype[Symbol.search]
  • RegExp.prototype[Symbol.split]

即将 String实例对象中过得有关正则方法全部内置到RegExp对象中。


u修饰符

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

/^\uD83D/u.test('\uD83D\uDC2A') // false
/^\uD83D/.test('\uD83D\uDC2A') // true
// 详细参见字符串的扩展,字符串的unicode表示方式

常见的需要用到 u 修饰符的正则表达式

  • 点字符 .
    点字符在正则表达式中,含义是除了换行符以外的任意单个字符,对于码点大于 0xFFFF 的 Unicode 字符,点字符不能识别,必须加上 u 修饰符
  • Unicode字符表示法
    ES6 新增了使用大括号表示 Unicode字符,这种表示法在正则表达式中也必须加上 u 修饰符,才能够识别 否则会被解读为量词
  • 量词
    使用 u 修饰符后,所有量词都会正确识别码点大于 0xFFFF 的 Unicode 字符
  • 预定义模式
    \S是预定义模式,匹配所有非空白字符,只有加了 u 修饰符,它才能正确匹配码点大于 0xFFFF 的 Unicode 字符
  • 转义
    没有u修饰符的情况下,正则中没有定义的转义(如逗号的转义\,无效,而在u模式会报错。

y 修饰符

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

var s = 'aaa_aa_a';
var r1 = /a+/g;
var r2 = /a+/y;

r1.exec(s) // ["aaa"]
r2.exec(s) // ["aaa"]

r1.exec(s) // ["aa"]
r2.exec(s) // null // 因为这里会从 _ 开始寻找,未找到返回null

var s = 'aaa_aa_a';
var r = /a+_/y;

r.exec(s) // ["aaa_"] 
r.exec(s) // ["aa_"]

y修饰符的设计本意,就是让头部匹配的标志^在全局匹配中都有效。

g修饰符会忽略非法字符,y修饰符则不会


s 修饰符

正则表达式中,. 是一个特殊字符,代表任意的单个字符,但是有两个例外

  • 四个字节的 UTF-16 字符,可以用 u 修饰符解决

  • 行终止符

    • U+000A 换行符(\n
    • U+000D 回车符(\r
    • U+2028 行分隔符(line separator)
    • U+2029 段分隔符(paragraph separator)

    ES2018 引入 s 修饰符,使得.可以匹配任意单个字符。

    这被称为 dotAll 模式,即 . 代表一切字符。所以,正则表达式还引入了一个 dotAll 属性 表示是否处于 dotAll 模式


RegExp.prototype 上的属性及方法

RegExp.prototype.unicode

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

RegExp.prototype.sticky

表示是否设置了y修饰符

RegExp.prototype.flags

返回设置的修饰符

String.prototype.matchAll()

如果一个正则表达式在字符串里面有多个匹配,现在一般使用g修饰符或y修饰符,在循环里面逐一取出。

ES2020 增加了String.prototype.mathchAll()方法,可以一次性取出所有匹配,不过它返回的是一个遍历器,而不是数组
相对于返回数组,返回遍历器的好处在于,如果匹配结果是一个很大的数组,那么遍历器比较节省资源。
遍历器转为数组是非常简单的,使用...运算符和Array.from()方法就可以了

// 转为数组的方法一
[...string.matchAll(regex)]

// 转为数组的方法二
Array.from(string.matchAll(regex))

后行断言

js语言的正则表达式,只支持先行断言和先行否定断言,不支持后行断言和后行否定断言,ES2018引入后行断言

Unicode 属性类

ES2018 引入了一种新的类的写法\p{...}\P{...},允许正则表达式匹配符合 Unicode 某种属性的所有字符。

const regexGreekSymbol = /\p{Script=Greek}/u;
regexGreekSymbol.test('π') // true
// 上面代码中
// \p{Script=Greek}指定匹配一个希腊文字母,所以匹配π成功。

Unicode 属性类要制定属性名和属性值

对于某些属性,可以只写属性名

\P{…}\p{…}的反向匹配,即匹配不满足条件的字符。

注意,这两种类只对 Unicode 有效,所以使用的时候一定要加上u修饰符。如果不加u修饰符,正则表达式使用\p\P会报错,ECMAScript 预留了这两个类。

\p{Number}甚至能匹配罗马数字。

具名组匹配

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

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[1])引用,要是组的顺序变了,引用的时候就必须修改序号。

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

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"

“具名组匹配”在圆括号内部,模式的头部添加“问号 + 尖括号 + 组名”(?<year>),然后就可以在exec方法返回结果的groups属性上引用该组名。同时,数字序号matchObj[1])依然有效。

如果具名组没有匹配,那么对应的groups对象属性会是undefined

解构赋值和替换

  • 有了具名组匹配以后,可以使用解构赋值直接从匹配结果上为变量赋值。

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

引用
如果要在正则表达式内部引用某个“具名组匹配”,可以使用\k<组名>的写法。


总结

本文主要介绍了,ES6以来对正则表达式的扩展,主要有RegExp构造函数及其原型上的属性,字符串的正则方法,各种修饰符,以及居名组匹配等等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值