正则扩展
RegExp方法
var regex = new RegExp('xyz', 'i'); // 等价于 var regex = /xyz/i; var regex = new RegExp(/xyz/, 'i'); //error es5会直接报错 new RegExp(/abc/ig, 'i').flags // "i" es6会直接替换原有修饰符u修饰符
正则添加了修饰符 表示为”Unicode 模式”
/^\uD83D/u.test('\uD83D\uDC2A') // false /^\uD83D/.test('\uD83D\uDC2A') // true点字符 加上u可以识别整个中文字符 var s = ‘��’;
/^. /.test(s)//false/. / . t e s t ( s ) / / f a l s e / . /u.test(s) // true
Unicode字符表示法 /\u{61}/.test(‘a’) // false /\u{61}/u.test(‘a’) // true /\u{20BB7}/u.test(‘��’) // true量词会正确识别Unicode字符 /a{2}/.test(‘aa’) // true /a{2}/u.test(‘aa’) // true /��{2}/.test(‘����’) // false /��{2}/u.test(‘����’) // true预定义 能正常识别Unicode字符 /^\S /.test(‘��′)//false/§ / . t e s t ( ‘ � � ′ ) / / f a l s e / § /u.test(‘��’) // truei 修饰符 /[a-z]/i.test(‘\u212A’) // false /[a-z]/iu.test(‘\u212A’) // truey修饰符
下次匹配必须与上次匹配的剩余位置的第一个位置开始 其实就是必须从头开始匹配
var s = 'aaa_aa_a'; var r1 = /a+/g; var r2 = /a+/y; r1.exec(s) // ["aaa"] r2.exec(s) // ["aaa"] r1.exec(s) // ["aa"] r2.exec(s) // nully修饰符同样遵守lastIndex属性,但是要求必须在lastIndex指定的位置发现匹配。
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单单一个y修饰符对match方法,只能返回第一个匹配,必须与g修饰符联用,才能返回所有匹配。
'a1a2a3'.match(/a\d/y) // ["a1"] 'a1a2a3'.match(/a\d/gy) // ["a1", "a2", "a3"]g会忽略非法字符而y不会 容易出现错误
sticky属性
判断正则是否设置了y修饰符
var r = /hello\d/y; r.sticky // trueflags属性
// ES5 的 source 属性 // 返回正则表达式的正文 /abc/ig.source // "abc" // ES6 的 flags 属性 // 返回正则表达式的修饰符 /abc/ig.flags // 'gi's修饰符
.表示特殊字符但是不包括 换行 回车 行分隔符 段分隔符 中文字体(用 u修饰符解决) ,加了s修饰符之后,可以匹配任意字符
/foo.bar/s.test('foo\nbar') // truedotAll属性 判断正则是否有s修饰符
const re = /foo.bar/s; // 另一种写法 // const re = new RegExp('foo.bar', 's'); re.test('foo\nbar') // true re.dotAll // true re.flags // 's'后行断言
es5
只支持先行断言 和先行否定断言
先行断言 /\d+(?=%)/.exec(‘100% of US presidents’) // [“100”]先行否定断言 /\d+(?!%)/.exec(‘that’s all 44 of them’) // [“44”]es6
还支持后行断言 后行否定断言
/(?<=\$)\d+/.exec('Benjamin Franklin is on the $100 bill') // ["100"] /(?<!\$)\d+/.exec('it’s is worth about €90') // ["90"](/1)引用组 必须在组的前面
/(?<=(o)d\1)r/.exec('hodor') // null /(?<=\1d(o))r/.exec('hodor') // ["r", "o"]Unicode属性类
ES2018 引入了一种新的类的写法\p{…}和\P{…},允许正则表达式匹配符合 Unicode 某种属性的所有字符。
const regexGreekSymbol = /\p{Script=Greek}/u; regexGreekSymbol.test('π') // true\p{Number}甚至能匹配罗马数字。
const regex = /^\p{Number}+$/u; regex.test('²³¹¼½¾') // true regex.test('㉛㉜㉝') // true regex.test('ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ') // true具名组匹配
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 re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u; '2015-01-02'.replace(re, '$<day>/$<month>/$<year>') // '02/01/2015'引用具名组
\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') // falseString.prototype.matchAll
可以获取匹配的所有字符串
const string = 'test1test2test3'; // g 修饰符加不加都可以 const regex = /t(e)(st(\d?))/g; for (const match of string.matchAll(regex)) { console.log(match); }可以用Array.from方法直接比那里
// 转为数组方法一 [...string.matchAll(regex)] // 转为数组方法二 Array.from(string.matchAll(regex));