乐趣区

关于es6:ES6学习-第五章-正则的扩展

前言

本章介绍正则的扩大。有些不罕用的常识理解即可。
本章原文链接:正则的扩大

RegExp 构造函数

从 ES6 开始,如果 RegExp 构造函数第一个参数是一个正则对象,并且第二个标记存在且为标记参数,将不再抛出 TypeError,将应用这些参数创立一个新的正则表达式。原有的正则表达式修饰符将被疏忽

const flag = new RegExp(/[0-9]/ig, 'i').flags; // 原有修饰符卫 ig,被 i 给代替了
console.log(flag); // i

字符串无关正则表达式

ES6 将之前字符串上的四个对于正则表达式的办法全副更改为 RegExp 的实例办法,所以当初所有与正则表达式无关的办法,全副定义在 RegExp 对象上。

  • String.prototype.match 调用 RegExp.prototype[Symbol.match]
  • String.prototype.replace 调用 RegExp.prototype[Symbol.replace]
  • String.prototype.search调用 RegExp.prototype[Symbol.search]
  • String.prototype.split调用 RegExp.prototype[Symbol.split]

flags 属性

RegExp.prototype.flags 属性 是 ES6 新增属性,会返回正则表达式的修饰符。

const SAMPLEREG = /abc/ig;
console.log(SAMPLEREG.flags); // gi

u 修饰符

在 ES6 中新增了 u修饰符,示意应用 Unicode 码的模式进行匹配。解决大于 \uFFFFUnicode 字符

留神

一旦加上 u 润饰符号,就会批改上面这些正则表达式的行为。

  1. 点字符

对于码点大于 0xFFFFUnicode 字符,点字符不能辨认,必须加上 u 修饰符。

  1. **Unicode** 字符表示法

新增了应用大括号示意 Unicode 字符,这种表示法在正则表达式中必须加上 u 修饰符,能力辨认当中的大括号,否则会被解读为量词。

  1. 量词

应用 u 修饰符后,所有量词都会正确识别码点大于 0xFFFFUnicode 字符。

  1. 预约义模式

u修饰符也影响到预约义模式,是否正确识别码点大于 0xFFFF 的 Unicode 字符。

  1. i 修饰符

有些 Unicode 字符的编码不同,然而字型很相近,比方,\u004B\u212A 都是大写的K

  1. 本义

没有 u 修饰符的状况下,正则中没有定义的本义(如逗号的本义\,)有效,而在 u 模式会报错。

unicode 属性

RegExp.prototype.unicode 属性表明正则表达式带有 ”u” 标记。unicode 是正则表达式独立实例的只读属性。

const SAMPLEREG = /abc/u;

console.log(SAMPLEREG.flags); // u
console.log(SAMPLEREG.unicode); // true

Unicode 属性类

**Unicode property escapes**
ES2018 引入了一种新的类的写法 \p{...} 和 \`P{…},用于解决 JavaScript 没有强无效的形式用匹配出不同文字问题。容许正则表达式匹配合乎 Unicode` 某种属性的所有字符。

\p{Unicode 属性名 =Unicode 属性值}
// 对于某些属性,能够只写属性名,或者只写属性值。\p{Unicode 属性值}
\p{Unicode 属性名}

// \P 为 \p 取反
\P{Unicode 属性值}
\P{Unicode 属性名}

留神:
这两品种只对 Unicode 无效,所以应用的时候肯定要加上 u 修饰符。
\P{…}\p{…} 的反向匹配,即匹配不满足条件的字符。

const SAMPLEREG = /\p{Script=Greek}/u;
SAMPLEREG.test('π'); // true

y 修饰符

y 修饰符的作用

在 ES6 中新增了 y 修饰符,示意执行“粘性(sticky)”搜寻, 匹配从指标字符串的以后地位开始。

y修饰符与 g 修饰符类似,都是全局匹配,后一次匹配从上一次匹配胜利的下一个地位开始。
区别是:g修饰符只有残余地位中存在匹配即可;而 y 修饰符必须从残余的第一个地位开始匹配。

// y 修饰符与 g 修饰符的区别
const SAMPLE = 'abcdabcd';
const SAMPLEREG1 = /abcd/g;
const SAMPLEREG2 = /abcda/y;

console.log(SAMPLEREG1.test(SAMPLE)); // true
console.log(SAMPLEREG2.test(SAMPLE)); // true
console.log(SAMPLEREG1.test(SAMPLE)); // true
console.log(SAMPLEREG2.test(SAMPLE)); // false

留神

实际上,y润饰符号隐含了头部匹配的标记^

const SAMPLEREGGY = /ab/gy;
const SAMPLEREGY = /ab/y;

let sample1 = 'ababcabcd'.replace(SAMPLEREGGY, '-'); 
let sample2 = 'ababcabcd'.replace(SAMPLEREGY, '-');

// 最初一个 ab 因为不是呈现在下一次匹配的头部,所以不会被替换。console.log(sample1);
// 只能返回第一个匹配,必须与 g 修饰符联用,能力返回所有匹配。console.log(sample2);

sticky 属性

RegExp.prototype.sticky示意是否设置了 y 修饰符。sticky 是正则表达式对象的只读属性。

const SAMPLEREG = /a/gy;
console.log(SAMPLEREG.sticky); // true

s 修饰符

ES2018 引入 s 修饰符,使得 . 能够匹配任意单个字符。包含行终止符(line terminator character)。

行终止符

所谓 行终止符 ,就是该字符示意一行的终结。以下四个字符属于“ 行终止符”。

  • U+000A 换行符(\n
  • U+000D 回车符(\r
  • U+2028 行分隔符(line separator
  • U+2029 段分隔符(paragraph separator
const SAMPLEREG = /ab.cd/s;
console.log(SAMPLEREG.test('ab\ncd') ); // true

dotAll

下面这种状况被称为 **dotAll** 模式 ,即点(dot)代表所有字符。正则表达式还引入了一个**dotAll** 属性
dotAll 属性返回一个布尔值,表明是否在正则表达式中一起应用 ”s“ 修饰符。dotAll 是一个只读的属性,属于单个正则表达式实例。

    const SAMPLEREG = /ab.cd/s;
    const sample = SAMPLEREG.test('ab\ncd');
    console.log(SAMPLEREG.flags); // s
    console.log(SAMPLEREG.dotAll); // true

后行断言

ES2018 引入后行断言,V8 引擎 4.9 版(Chrome 62)曾经反对。

  • 后行断言
    x 只有在 y 后面才匹配,必须写成 /x(?=y)/
    比方,只匹配百分号之前的数字,要写成/\d+(?=%)/
  • 后行否定断言
    x 只有不在 y 后面才匹配,必须写成 /x(?!y)/
    比方,只匹配不在百分号之前的数字,要写成/\d+(?!%)/
  • 后行断言 正好与 后行断言 相同,
    x只有在 y 前面才匹配,必须写成 /(?<=y)x/
    比方,只匹配美元符号之后的数字,要写成/(?<=\$)\d+/
  • 后行否定断言 则与 后行否定断言 相同,
    x只有不在 y 前面才匹配,必须写成 /(?<!y)x/
    比方,只匹配不在美元符号前面的数字,要写成/(?<!\$)\d+/

后行断言须要先匹配 /(?<=y)x/x,而后再回到右边,匹配 y 的局部。程序为 先右后左

// 后行断言
const sample1 = /\d+(?=%)/.exec('100% of US presidents have been male');
// 后行否定断言
const sample2 = /\d+(?!%)/.exec('that’s all 44 of them');
console.log(sample1);  // 100
console.log(sample2);  // 44

// 后行断言
const sample3 = /(?<=\$)\d+/.exec('Benjamin Franklin is on the $100 bill');
// 后行否定断言
const sample4 = /(?<!\$)\d+/.exec('it’s is worth about €90');
console.log(sample3);  // 100
console.log(sample4);  // 90

组匹配

正则表达式的括号示意分组匹配,括号中的模式能够用来匹配分组的内容。

ES2018 引入了 具名组匹配(Named Capture Groups),容许为每一个组匹配指定一个名字,既便于浏览代码,又便于援用。
具名组匹配 在圆括号外部,模式的头部增加“问号 + 尖括号 + 组名”(?<year>),而后就能够在 exec 办法返回后果的 groups 属性上援用该组名。同时,数字序号仍然无效。

const sampleUsers = `
姓刘名备字玄德
姓关名羽字云长
姓张名飞字翼德 `;
const SAMPLEREG = / 姓 (?<surnames>.+) 名(?<name>.+)字(?<word>.+)/g;
let result = SAMPLEREG.exec(sampleUsers);

do {console.log(`${result.groups.surnames}${result.groups.name}${result.groups.surnames}${result.groups.word}`);
} while ((result = SAMPLEREG.exec(sampleUsers)) !== null);

/*
* 刘备刘玄德
* 关羽关云长
* 张飞张翼德
*/

下面的代码中:?<xxx>的作用就是为这个匹配定义一个组名,在匹配的 groups 属性中能够查看到匹配的组名,这里能够应用 解构赋值 间接从匹配后果上为变量赋值。

留神:如果要在正则表达式外部援用某个 具名组匹配 ,能够应用\k< 组名 > 的写法

matchAll()

ES2020 减少了 String.prototype.matchAll() 办法,能够一次性取出所有匹配。不过,它返回的是一个遍历器 / 迭代器(Iterator),而不是数组。

const string = 'sample1sample2sample3';
const regex = /sample/g;

for (const match of string.matchAll(regex)) {console.log(match);
}
// 遍历输入
/*
['sample', index: 0, input: 'sample1sample2sample3', groups: undefined]
['sample', index: 7, input: 'sample1sample2sample3', groups: undefined]
['sample', index: 14, input: 'sample1sample2sample3', groups: undefined]
*/
退出移动版