ECMAScript 6 学习笔记(四):正则的扩展
栏目: JavaScript · 发布时间: 5年前
内容简介:“Unicode 模式”,用来正确处理大于\uFFFF的 Unicode 字符。正则实例对象新增 unicode 属性,表示是否设置了 u 修饰符。“粘连”(sticky)修饰符,y 修饰符的作用与 g 修饰符类似,也是全局匹配,后一次匹配都从上一次匹配成功的下一个位置开始。不同之处在于,g 修饰符只要剩余位置中存在匹配就可,而 y 修饰符确保匹配必须从剩余的第一个位置开始,这也就是“粘连”的涵义。y 修饰符的设计本意,就是让头部匹配的标志 ^ 在全局匹配中都有效。
u 修饰符
“Unicode 模式”,用来正确处理大于\uFFFF的 Unicode 字符。
/^\uD83D/u.test('\uD83D\uDC2A') // false /^\uD83D/.test('\uD83D\uDC2A') // true
正则实例对象新增 unicode 属性,表示是否设置了 u 修饰符。
y 修饰符
“粘连”(sticky)修饰符,y 修饰符的作用与 g 修饰符类似,也是全局匹配,后一次匹配都从上一次匹配成功的下一个位置开始。不同之处在于,g 修饰符只要剩余位置中存在匹配就可,而 y 修饰符确保匹配必须从剩余的第一个位置开始,这也就是“粘连”的涵义。y 修饰符的设计本意,就是让头部匹配的标志 ^ 在全局匹配中都有效。
const REGEX = /a/y; // 指定从2号位置开始匹配 REGEX.lastIndex = 2; // 不是粘连,匹配失败 REGEX.exec('xaya') // null // 指定从3号位置开始匹配 REGEX.lastIndex = 3; // 3号位置是粘连,匹配成功 const match = REGEX.exec('xaya'); match.index // 3 REGEX.lastIndex // 4
ES6 的正则实例对象多了 sticky 属性,表示是否设置了 y 修饰符。
s 修饰符
ES6 之前,正则中的“.”无法匹配四个字节的 UTF-16 字符与行终止符,因此 ES6 引入了 s 修饰符,也被称为 dotAll 模式,即点(dot)代表一切字符。同时,正则表达式还引入了一个 dotAll 属性,返回一个布尔值,表示该正则表达式是否处在dotAll模式。
/foo.bar/.test('foo\nbar') // false /foo.bar/s.test('foo\nbar') // true
flag 属性
ES6 为正则表达式新增了 flags 属性,会返回正则表达式的修饰符。
// ES5 的 source 属性,返回正则表达式的正文 /abc/ig.source // "abc" // ES6 的 flags 属性,返回正则表达式的修饰符 /abc/ig.flags // 'gi'
后行断言
JavaScript 语言的正则表达式,只支持先行断言(lookahead)和先行否定断言(negative lookahead),不支持后行断言(lookbehind)和后行否定断言(negative lookbehind)。ES2018 引入后行断言,V8 引擎 4.9 版(Chrome 62)已经支持。
至此,JavaScript 终于完美支持这四种匹配方法:
// 先行断言,匹配匹配项前面的内容 /\d+(?=%)/.exec('100% of US presidents have been male') // ["100"] /\d+(?!%)/.exec('that’s all 44 of them') // ["44"] // 后行断言,匹配匹配项后面的内容 /(?<=\$)\d+/.exec('Benjamin Franklin is on the $100 bill') // ["100"] /(?<!\$)\d+/.exec('it’s is worth about €90') // ["90"]
与其他正则操作相反,后行断言的匹配方式是“先右后左”,即后行断言是先从左到右扫描,发现匹配以后再回过头,从右到左完成匹配,因此可能会导致不符合预期的行为:
/(?<=(\d+)(\d+))$/.exec('1053') // ["", "1", "053"] /^(\d+)(\d+)$/.exec('1053') // ["1053", "105", "3"]
Unicode 属性类
ES2018 引入了一种新的类: \p{}
和 \P{}
,允许正则表达式匹配符合 Unicode 某种属性的所有字符。其中 \P{}
是 \p{}
的反向匹配,即匹配不满足条件的字符。需要注意的是,这两种类只对 Unicode 有效,所以使用的时候一定要加上 u 修饰符。
const regexGreekSymbol = /\p{Script=Greek}/u; regexGreekSymbol.test('π') // true
具名组匹配
正则表达式使用圆括号进行组匹配,使用 exec() 就可以将匹配结果提取出来。
const RE_DATE = /(\d{4})-(\d{2})-(\d{2})/; const matchObj = RE_DATE.exec('2019-12-31'); const year = matchObj[1]; // 2019 const month = matchObj[2]; // 12 const day = matchObj[3]; // 31
为了方便使用,采用具名组匹配,可以为每一个组指定名字
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
有了具名组匹配以后,可以使用解构赋值直接从匹配结果上为变量赋值。
let {groups: {one, two}} = /^(?<one>.*):(?<two>.*)$/u.exec('foo:bar'); one // foo two // bar
如果要在正则表达式内部引用某个“具名组匹配”,可以使用\k<组名>的写法。
const RE_TWICE = /^(?<word>[a-z]+)!\k<word>$/; RE_TWICE.test('abc!abc') // true RE_TWICE.test('abc!ab') // false
数字引用(\1)依然有效。
const RE_TWICE = /^(?<word>[a-z]+)!\1$/; RE_TWICE.test('abc!abc') // true RE_TWICE.test('abc!ab') // false
字符串取得所有匹配
使用 String.prototype.matchAll 方法,可以一次性取出所有匹配。不过,它返回的是一个遍历器(Iterator),而不是数组。
const string = 'test1test2test3'; // g 修饰符加不加都可以 const regex = /t(e)(st(\d?))/g; for (const match of string.matchAll(regex)) { console.log(match); } // ["test1", "e", "st1", "1", index: 0, input: "test1test2test3"] // ["test2", "e", "st2", "2", index: 5, input: "test1test2test3"] // ["test3", "e", "st3", "3", index: 10, input: "test1test2test3"]
上面代码中,由于 string.matchAll(regex) 返回的是遍历器,所以可以用 for…of 循环取出。相对于返回数组,返回遍历器的好处在于,如果匹配结果是一个很大的数组,那么遍历器比较节省资源。除此之外,额可以使用 … 运算符和 Array.from 方法将遍历器转为数组。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- ES6入门之正则的扩展
- 带答案面经分享-L1正则&L2正则
- 神经网络中的网络优化和正则化(四):正则化
- 正则表达式 – 如何使用正则表达式进行Erlang模式匹配?
- 正则表达式创建方式的区别及编写简单的正则方式(js学习总结)
- JavaScript正则表达
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。