@xiaoyixy
2018-11-08T09:05:53.000000Z
字数 4058
阅读 1311
Note ES6 ECMAScript6
第一个参数为正则表达式而第二个标志参数存在时,
new RegExp(/ab+c/, 'i')不再抛出 TypeError
/ab+c/i;new RegExp('ab+c', 'i');new RegExp(/ab+c/, 'i');new RegExp(/ab+c/, 'i');// Starting with ECMAScript 6, new RegExp(/ab+c/, 'i') no longer throws a TypeError ("can't supply flags when constructing one RegExp from another") when the first argument is a RegExp and the second flags argument is present. A new RegExp from the arguments is created instead.
Unicode; 将模式视为 Unicode 序列点的序列,用来正确处理大于 \uFFFF 的 Unicode 字符
// \uD83D\uDC2A是一个四个字节的 UTF-16 编码,代表一个字符// ES5 不支持四个字节的 UTF-16 编码,会将其识别为两个字符/^\uD83D/u.test('\uD83D\uDC2A') // false/^\uD83D/.test('\uD83D\uDC2A') // true// 1. 对于码点大于0xFFFF的 Unicode 字符,点字符(.)不能识别,必须加上 u 修饰符。var s = '𠮷';/^.$/.test(s) // false/^.$/u.test(s) // true// 2. ES6 新增了使用大括号表示 Unicode 字符,这种表示法在正则表达式中必须加上u修饰符,才能识别当中的大括号,否则会被解读为量词。/\u{61}/.test('a') // false/\u{61}/u.test('a') // true/\u{20BB7}/u.test('𠮷') // true// 3. 使用u修饰符后,所有量词都会正确识别码点大于0xFFFF的 Unicode 字符。/a{2}/.test('aa') // true/a{2}/u.test('aa') // true/𠮷{2}/.test('𠮷𠮷') // false/𠮷{2}/u.test('𠮷𠮷') // true// 4. 预定义模式// 下面代码的\S是预定义模式,匹配所有非空白字符。只有加了u修饰符,它才能正确匹配码点大于0xFFFF的 Unicode 字符。/^\S$/.test('𠮷') // false/^\S$/u.test('𠮷') // true// 5. i 修饰符// 有些 Unicode 字符的编码不同,但是字型很相近,比如,\u004B与\u212A都是大写的K/[a-z]/i.test('\u212A') // false/[a-z]/iu.test('\u212A') // true
粘性匹配; 仅匹配目标字符串中此正则表达式的 lastIndex 属性指示的索引(并且不尝试从任何后续的索引匹配)。
// gvar regex1 = RegExp('foo*','g');var regex2 = RegExp('foo*','y');var str1 = 'football, foosball';var array1, array2;while ((array1 = regex1.exec(str1)) !== null) {console.log(`Found ${array1[0]}. Next starts at ${regex1.lastIndex}.`);// "Found foo. Next starts at 3."// "Found foo. Next starts at 13."}// ywhile ((array2 = regex2.exec(str1)) !== null) {console.log(`Found ${array2[0]}. Next starts at ${regex2.lastIndex}.`);// "Found foo. Next starts at 3."}
单单一个y修饰符对match方法,只能返回第一个匹配,必须与g修饰符联用,才能返回所有匹配。
'a1a2a3'.match(/a\d/y) // ["a1"]'a1a2a3'.match(/a\d/gy) // ["a1", "a2", "a3"]
ES2018 引入s修饰符,使得.可以匹配任意单个字符。
正则表达式中,点(.)是一个特殊字符,代表任意的单个字符,但是有两个例外。一个是四个字节的 UTF-16 字符,这个可以用u修饰符解决;另一个是行终止符(line terminator character)。
/foo.bar/.test('foo\nbar') // false/foo[^]bar/.test('foo\nbar') // true// ES2018/foo.bar/s.test('foo\nbar') // true
JavaScript 语言的正则表达式,只支持先行断言(lookahead)和先行否定断言(negative lookahead),不支持后行断言(lookbehind)和后行否定断言(negative lookbehind)。ES2018 引入后行断言,V8 引擎 4.9 版(Chrome 62)已经支持。
/x(?=y)//x(?!y)//(?<=y)x//(?<!y)x/
/\d+(?=%)/.exec('100% of US presidents have been male') // ["100"]/\d+(?!%)/.exec('that’s all 44 of them') // ["44"]/(?<=\$)\d+/.exec('Benjamin Franklin is on the $100 bill')// ["100"]/(?<!\$)\d+/.exec('it’s is worth about €90')// ["90"]
“后行断言”的实现,需要先匹配/(?<=y)x/的x,然后再回到左边,匹配y的部分。这种“先右后左”的执行顺序,与所有其他正则操作相反,导致了一些不符合预期的行为。
/(?<=(\d+)(\d+))$/.exec('1053') // ["", "1", "053"]/^(\d+)(\d+)$/.exec('1053') // ["1053", "105", "3"]/(?<=(o)d\1)r/.exec('hodor') // null/(?<=\1d(o))r/.exec('hodor') // ["r", "o"]
ES2018 引入了一种新的类的写法\p{...}和\P{...},允许正则表达式匹配符合 Unicode 某种属性的所有字符。
Unicode 属性类要指定属性名和属性值。
\p{UnicodePropertyName=UnicodePropertyValue}
对于某些属性,可以只写属性名,或者只写属性值。
\p{UnicodePropertyName}\p{UnicodePropertyValue}
\P{…} 是 \p{…} 的反向匹配,即匹配不满足条件的字符。
注意,这两种类只对 Unicode 有效,所以使用的时候一定要加上u修饰符。如果不加u修饰符,正则表达式使用\p和\P会报错,ECMAScript 预留了这两个类。
const regexGreekSymbol = /\p{Script=Greek}/u;regexGreekSymbol.test('π') // true
正则表达式使用圆括号进行组匹配。
const RE_DATE = /(\d{4})-(\d{2})-(\d{2})/;const matchObj = RE_DATE.exec('1999-12-31');const year = matchObj[1]; // 1999const month = matchObj[2]; // 12const day = matchObj[3]; // 31
ES2018 引入了具名组匹配(Named Capture Groups),允许为每一个组匹配指定一个名字,既便于阅读代码,又便于引用。
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; // 1999const month = matchObj.groups.month; // 12const day = matchObj.groups.day; // 31
如果要在正则表达式内部引用某个“具名组匹配”,可以使用\k<组名>的写法。
const RE_TWICE = /^(?<word>[a-z]+)!\k<word>$/;RE_TWICE.test('abc!abc') // trueRE_TWICE.test('abc!ab') // false// 数字引用(\1)依然有效。const RE_TWICE = /^(?<word>[a-z]+)!\1$/;RE_TWICE.test('abc!abc') // trueRE_TWICE.test('abc!ab') // false