【ES6】学习笔记:正则扩展

170 阅读6分钟

博文类型: 学习向
背景: 学习ES6语法并做学习笔记
目标: 跟着ES6教程实操,并记录实操结果

一、u 修饰符

作用: es5 正则无法识别 4 个字节的字符(unicode 大于\uFFFF),es6 新增 u 修饰符后就可以识别 4 个字节的字符。

console.log(/^\uD83D/u.test("\uD83D\uDC2A"));
//false \uD83D\uDC2A识别为一个字符

console.log(/^\uD83D/.test("\uD83D\uDC2A"));
//true \uD83D\uDC2A识别为两个字符

1.点字符

作用: 点字符在正则表达式中的含义是除了换行符以外的任意单个字符。对于码点大于 0xFFFF 的字符,点字符不能识别,必须加上 u 修饰符。

let val = "𠮷a"; //码点:0x20BB7,UTF-16:0xD842 0xDFB7,十进制:55362 57271
console.log(/^.$/.test(val));
//false

console.log(/^.$/u.test(val));
//true

2.Unicode字符表示法

作用: es6新增了使用大括号表示Unicode字符,但是正则表达式中必须要加上u,否则会被识别为量词。

console.log(/\u{61}/.test("a"));
//false

console.log(/\u{61}/u.test("a"));
//true

3.量词

作用: 匹配连续字符。

console.log(/a{2}/.test("a"));
//false

console.log(/a{2}/.test("aa"));
//true

console.log(/𠮷{2}/.test("𠮷"));
//false

console.log(/𠮷{2}/u.test("𠮷𠮷"));
//true

4.预定义模式

作用: \S是预定义模式,他能匹配所有不是空格的字符。但是只有加了u修饰符,他才能正确匹配码点大于0xFFFF的字符串。

console.log(/^\S$/.test("𠮷"));
//false

console.log(/^\S$/u.test("𠮷"));
//true

二、y 修饰符

1.基本使用

作用: y修饰符,叫作“粘连”修饰符。y修饰符与g修饰符类似,都是全局匹配,不同之处在于,g修饰符第二次匹配只需要剩余部分存在匹配就可以,y修饰符的第二次匹配则需要从剩余部分的第一个位置开始匹配。

let a='aaa_aa_a'
let r1=/a+/g
let r2=/a+/y
console.log(r1.exec(a));
//['aaa']

console.log(r2.exec(a));
//['aaa']

console.log(r1.exec(a));
//['aa']

console.log(r2.exec(a));
//null

debugger

解释: 第一次匹配都能获得‘aaa’,剩余字段‘_aa_a’。 第二次匹配,g修饰符可以直接在剩余字段中进行匹配,而y修饰符则会从剩余字符的第一个位置开始匹配,剩余字段的第一个字符与匹配规则不符,则返回null。

2.lastIndex属性

作用: 开始匹配的位置。

let a='aaa_aa_a'
let r2=/a+/y
r2.lastIndex=4
let b=r2.exec(a)
console.log(b.index);
//4

console.log(r2.exec(a));
//null

r2.lastIndex=7
console.log(r2.exec(a));
//['a']

debugger

解释: 第一次匹配位置计数是从0开始的,r2.lastIndex=4表示从位置计数为4的字符(包含位置计数为4的字符)开始匹配。匹配规则可以匹配到'aa',匹配到的位置计数为4(b.index)。 第二次匹配是从位置计数6开始的,位置计数6的字符是'_',不符合匹配规则,返回null。 第三次匹配从位置计数是7的字符开始匹配,可以匹配到'a'。

3.g、y修饰符合用

作用: 返回全部符合规则的连续的字符。

let r1=/a\d/g
let r2=/a\d/y
console.log('a1a2a3 ' .match(r1));
//['a1', 'a2', 'a3']

console.log('a1a2a3 ' .match(r2));
//['a1']

console.log('a1a2a3 ' .match(r2));
//['a2']

console.log('a1a2a3 ' .match(r2));
//['a3']

console.log('a1a2a3 ' .match(/a\d/gy));
//['a1', 'a2', 'a3']

console.log('a1a2a3 ' .match(/a\d/yg));
//['a1', 'a2', 'a3']

debugger

解释: g修饰符能够返回所有与规则向匹配的字符,y修饰符能够返回第一个从第一个位置开始匹配规则的字符。gy能够返回从第一个位置开始符合匹配规则的所有字符,且gy与yg不用区分先后。

4.sticky属性

作用: 是否用了y修饰符。

let r1=/a\d/g
let r2=/a\d/y
console.log(r1.sticky);
//false

console.log(r2.sticky);
//true

debugger

5.falgs属性

作用: 返回正则表达式的修饰符。

let r1=/a\d/gy
console.log(r1.flags);
//gy

debugger

6.source属性

作用: 返回正则表达式正文。

let r1=/a\d/gy
console.log(r1.source);
//a\d

debugger

三、s 修饰符:dotAll模式

作用: 使得点字符可以匹配所有的字符。

console.log(/foo.bar/.test('foo\nbar'));
//false

console.log(/foo.bar/s.test('foo\nbar'));
//true

debugger

解释: 点字符可以匹配任意单个字符,但是无法匹配行终止符。 以下四个属于行终止符: U+000A 换行符(\n) U+000D 回车符(\r) U+2028 行分隔符( line separator) U+2029 段分隔符( paragraph separator) s修饰符可以使得点字符匹配行终止符。

1.dotAll属性

作用: 返回正则表达式是否处于dotAll模式下。

let r1=/foo.bar/s
console.log(r1.dotAll);
//true

debugger

解释: 点字符(dot)可以代表一切字符,则可称为 dotAll模式。

四、各种断言

1.先行断言

作用: x只有在y前面才匹配(正则:/x(?=y)/)。

let r1=/\d+(?=%)/g
console.log(r1.exec('100%222%123456'));
//['100']

console.log(r1.exec('100%222%123456'));
//['222']

debugger

解释: 匹配在百分号前的数字。

2.先行否定断言

作用: x只有不在y前面才匹配(正则:/x(?!y)/)

let r1=/\d+(?!%)/g
console.log(r1.exec('100%222%123456'));
//['10']

console.log(r1.exec('100%222%123456'));
//['22']

console.log(r1.exec('100%222%123456'));
//['123456']

debugger

解释: 匹配不在百分号前一位的数字。

3.后行断言

作用: x只有在y后面才匹配(正则:/(?<=y)x/)

let r1=/(?<=\$)\d+/g
console.log(r1.exec('100$222$123456'));
//['222']

console.log(r1.exec('100$222$123456'));
//['123456']

console.log(r1.exec('100$222$123456'));
//null

debugger

解释: 匹配美元符号后的数字。

4.后行否定断言

作用: x只有不在y后面才匹配(正则:/(?<!y)x/)

let r1=/(?<!\$)\d+/g
console.log(r1.exec('100$222$123456'));
//['100']

console.log(r1.exec('100$222$123456'));
//['22']

console.log(r1.exec('100$222$123456'));
//['23456']

debugger

解释: 匹配美元符号前的数字。

五、具名组匹配

1.简介

作用: 不再被顺序所束缚,将匹配出的数据赋予特定的含义。(正则:?<名字>)

let r1=/(\d{4})-(\d{2})-(\d{2})/
let re=r1.exec('1997-10-29')
console.log(re[1]);
//1997

console.log(re[2]);
//10

console.log(re[3]);
//29

let r2=/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/
let re2=r2.exec('1997-10-29')
console.log(re2.groups.year);
//1997

console.log(re2.groups.month);
//10

console.log(re2.groups.day);
//29

2.解构赋值和替换

1)解构赋值

作用: 能够通过解构赋值将具名匹配的结果赋值给变量。

let r1=/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/
let {groups:{year,month,day}}=r1.exec('1997-10-29')
console.log(year);
//1997

console.log(month);
//10

console.log(day);
//29

2)替换

//参数为变量
let r1=/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/
let re='1997-10-29'.replace(r1,'$<day>/$<month>/$<year>')
console.log(re);
//29/10/1997

//参数为函数
let r1=/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/
let re='1997-10-29'.replace(r1,(
	matched,//整个匹配结果
	capture1,//第一个组匹配
	capture2,//第二个组匹配
	capture3,//第三个组匹配
	position,//匹配开始的位置
	s,//原字符串
	groups//具名组构成的一个对象
)=>{
	console.log(matched,capture1,capture2,capture3,position,s,groups);
	debugger
})
//1997-10-29 1997 10 29 0 1997-10-29 {year: '1997', month: '10', day: '29'}

3.引用

作用: 可以在正则表达式中引用具名组匹配(正则:\k<名字>或\第几个具名组)

let r1=/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})-\k<year>/
let r2=/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})-\1/
let re1=r1.test('1997-10-29-1992')
console.log(re1);
//false

let re2=r1.test('1997-10-29-1997')
console.log(re2);
//true

let re3=r2.test('1997-10-29-1992')
console.log(re3);
//false

let re4=r2.test('1997-10-29-1997')
console.log(re4);
//true

解释: 可以通过两种方式在正则表达式中引用具名组匹配。 1.\k<组名> 2.\组序号(序号从1开始)