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]
RegExp.prototype.flags
属性 是ES6新增属性,会返回正则表达式的修饰符。const SAMPLEREG = /abc/ig;
console.log(SAMPLEREG.flags);
// gi
u 修饰符 在ES6中新增了
u
修饰符,表示使用Unicode
码的模式进行匹配。处理大于\uFFFF
的 Unicode
字符注意 一旦加上
u
修饰符号,就会修改下面这些正则表达式的行为。- 点字符
0xFFFF
的 Unicode
字符,点字符不能识别,必须加上u
修饰符。**Unicode**
字符表示法
Unicode
字符,这种表示法在正则表达式中必须加上u
修饰符,才能识别当中的大括号,否则会被解读为量词。- 量词
u
修饰符后,所有量词都会正确识别码点大于0xFFFF
的 Unicode
字符。- 预定义模式
u
修饰符也影响到预定义模式,能否正确识别码点大于0xFFFF的 Unicode 字符。i
修饰符
Unicode
字符的编码不同,但是字型很相近,比如,\u004B
与\u212A
都是大写的K
- 转义
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/
的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 = /(?
组匹配 正则表达式的括号表示分组匹配,括号中的模式可以用来匹配分组的内容。
ES2018 引入了具名组匹配(Named Capture Groups),允许为每一个组匹配指定一个名字,既便于阅读代码,又便于引用。
具名组匹配在圆括号内部,模式的头部添加“
问号 + 尖括号 + 组名”(?)
,然后就可以在exec
方法返回结果的groups
属性上引用该组名。同时,数字序号依然有效。const sampleUsers = `
姓刘名备字玄德
姓关名羽字云长
姓张名飞字翼德`;
const SAMPLEREG = /姓(?.+)名(?.+)字(?.+)/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);
/*
* 刘备刘玄德
* 关羽关云长
* 张飞张翼德
*/
上面的代码中:
?
的作用就是为这个匹配定义一个组名,在匹配的groups
属性中可以查看到匹配的组名,这里可以使用解构赋值直接从匹配结果上为变量赋值。
注意 : 如果要在正则表达式内部引用某个
具名组匹配,可以使用
\k<组名>
的写法
matchAll()
【ES6学习 第五章 正则的扩展】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]
*/
推荐阅读
- 野营记-第五章|野营记-第五章 讨伐梦魇兽
- 由浅入深理解AOP
- 继续努力,自主学习家庭Day135(20181015)
- python学习之|python学习之 实现QQ自动发送消息
- (二)ES6第一节变量(let|(二)ES6第一节变量(let,const)
- 六步搭建ES6语法环境
- 一起来学习C语言的字符串转换函数
- 定制一套英文学习方案
- 漫画初学者如何学习漫画背景的透视画法(这篇教程请收藏好了!)
- 《格列佛游记》第二卷第五章概括