文章目录
正则表达式
RegExp构造函数
RegExp构造函数第一个参数是正则对象,第二个参数可以指定修饰符,且覆盖原有的修饰符
new RegExp(/abc/efg,'i').flags
// "i"
字符串正则方法
es6将与正则相关的方法全部定义在RegExp对象上
- match():返回数组
- replace()
- search():返回索引
- split()
u修饰符
即“Unicode模式”,正确处理大于\uFFF的Unicode字符
点字符
对于码点大于0xFFFF的Unicode 字符,加上u
修饰符才能识别
Unicode字符表示法
es6新增大括号表示Unicode字符,但必须加上u
修饰符才能识别
/\u{61}/.test('a') // false
/\u{61}/u.test('a') // true
量词
加入u
修饰符后,所有量词都会正确识别码点大于0xFFF的Unicode字符
/a{2}/.test('aa') // true
/a{2}/u.test('aa') // true
预定义模式
u
修饰符也影响到预定义模式,能否正确识别码点大于0xFFFF的 Unicode 字符。
i修饰符
搜索时不区分大小写。
有些 Unicode 字符的编码不同,但是字型很相近,比如,\u004B与\u212A都是大写的K。
/[a-z]/i.test('\u212A') // false
/[a-z]/iu.test('\u212A') // true
转义
没有u修饰符的情况下,正则中没有定义的转义无效
/\,/ // /\,/
/\,/u // 报错
RegExp.prototype.unicode属性
unicode
属性表示是否设置了u
修饰符
const r1 = /hello/;
const r2 = /hello/u;
r1.unicode // false
r2.unicode // true
y修饰符
y
修饰符即"粘连"修饰符
y
修饰符的作用与g
修饰符类似,也是全局匹配,后一次匹配都从上一次匹配成功的下一个位置开始。不同之处在于,g
修饰符只要剩余位置中存在匹配就可,而y修饰符确保匹配必须从剩余的第一个位置开始。
sticky属性
标识是否设置了y
修饰符
var r = /hello\d/y;
r.sticky; //true
flags属性
返回正则表达式的修饰符
// ES5 的 source 属性
// 返回正则表达式的正文
/abc/ig.source
// "abc"
// ES6 的 flags 属性
// 返回正则表达式的修饰符
/abc/ig.flags
// 'gi'
s修饰符: dotAll模式
s
修饰符,使得.
可以匹配任意单个字符。
正则表达式还引入了一个dotAll
属性,返回一个布尔值,表示该正则表达式是否处在dotAll模式。
const re = /foo.bar/s;
// 另一种写法
// const re = new RegExp('foo.bar', 's');
re.test('foo\nbar') // true
re.dotAll // true
re.flags // 's'
后行断言
先行断言:x
只有在y
前面才匹配,必须写成/x(?=y)/
。比如,只匹配百分号之前的数字,要写成/\d+(?=%)/
。
先行否定断言:x
只有不在y
前面才匹配,必须写成/x(?!y)/
后行断言:正好与先行断言
相反,x
只有在y
后面才匹配,必须写成/(?<=y)x/
Unicode属性类
\p{…}:允许正则表达式匹配符合Unicode某种属性的所有字符
\P{…}:匹配不满足条件的字符
使用时需要加上u修饰符
具名组匹配
正则表达式用圆括号进行组匹配
const RE_DATE = /(\d{4})-(\d{2})-(\d{2})/;
具名组匹配允许为每一个组匹配指定一个名字
const RE_DATE = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
解构赋值和替换
使用具名组匹配后可以使用解构赋值直接从匹配结果上变为变量赋值
let {groups: {one, two}} = /^(?<one>.*):(?<two>.*)$/u.exec('foo:bar');
one // foo
two // bar
replace
的第二个参数可以是字符串或函数
let re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;
'2015-01-02'.replace(re, '$<day>/$<month>/$<year>')
// '02/01/2015'
'2015-01-02'.replace(re, (
matched, // 整个匹配结果 2015-01-02
capture1, // 第一个组匹配 2015
capture2, // 第二个组匹配 01
capture3, // 第三个组匹配 02
position, // 匹配开始的位置 0
S, // 原字符串 2015-01-02
groups // 具名组构成的一个对象 {year, month, day}
) => {
let {day, month, year} = groups;
return `${day}/${month}/${year}`;
});
引用
在正则表达式内部引用某个具名组匹配可以使用\k<组名>
的写法
const RE_TWICE = /^(?<word>[a-z]+)!\k<word>$/;
RE_TWICE.test('abc!abc') // true
RE_TWICE.test('abc!ab') // false
正则匹配索引
exec()
方法返回结果有一个index
的属性(匹配结果的开始位置)
indices
属性可以拿到匹配的开始位置和结束位置
const text = 'zabbcdef';
const re = /ab/;
const result = re.exec(text);
result.index // 1
result.indices // [ [1, 3] ]
matchAll()
正则表达式在字符串有多个匹配一般使用g
修饰符或y
修饰符在循环里逐一取出
var regex = /t(e)(st(\d?))/g;
var string = 'test1test2test3';
var matches = [];
var match;
while (match = regex.exec(string)) {
matches.push(match);
}
matches
// [
// ["test1", "e", "st1", "1", index: 0, input: "test1test2test3"],
// ["test2", "e", "st2", "2", index: 5, input: "test1test2test3"],
// ["test3", "e", "st3", "3", index: 10, input: "test1test2test3"]
// ]
matchAll()
可以一次性取出所有匹配,返回一个遍历器(Iterator)
const string = 'test1test2test3';
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"]
regexp.exec(str)
返回字符串str
中的regexp
匹配项
- 不带标志
g
,regexp.exec(str)
返回的第一个匹配与str.match(regexp).
完全相等 - 带标志
g
,下一次同样的调用会从位置 regexp.lastIndex 开始搜索,返回下一个匹配项,并将其后的位置保存在 regexp.lastIndex 中。
regexp.test(str)
查找匹配项,然后返回 true/false 表示是否存在