資料來源:ECMAScript 6 入門
資料整理:cashbook
- RegExp Constructor
- RegExp Methods
- The Flag of "u" (Unicode)
- The Flag of "y" (Sticky)
- The "sticky" Property
- The "flags" Property
- RegExp.escape()
- Lookbehind
ES5,在 RegExp 建構子內使用正則表達式,無法使用第二個參數
let regex = /xyz/i;
let regex = new RegExp('xyz', 'i');
let regex = new RegExp(/xyz/i);
let regex = new RegExp(/xyz/, 'i');
//error
ES6,可使用第二個參數,且 flag 會覆蓋
let regex = new RegExp(/xyz/ig, 'i');
let foo = regex.flags;
//i
RegExp.prototype[Symbol.match]
於內部被 String.prototype.match()
呼叫
其餘方法如replace
、search
、split
同上
'abc'.match(/a/);
/a/[Symbol.match]('abc');
//return same result
加上 u
flag 正確處理 UTF-16 編碼
/^\uD83D/.test('\uD83D\uDC2A');
// true
/^\uD83D/u.test('\uD83D\uDC2A');
// false
加上 u
flag,讓以下正則表達式的內容可以正確處理
- The Character "."
- Unicode Representation
- Occurrences
- Predefined Character Classes
- The Flag of "i" (ignore case)
加上 u
flag,讓 "." 可以正確處理 UTF-16 編碼
let s = '𠮷';
/^.$/.test(s); // false
/^.$/u.test(s); // true
\u{n}
用來表示Unicode
加上 u
flag,處理大括號內表示的 Unicode 字元
/\u{61}/.test('a'); // false
/\u{61}/u.test('a'); // true
加上 u
flag,讓 {n}
(出現次數)正確處理
/a{2}/.test('aa'); // true
/a{2}/u.test('aa'); // true
/𠮷{2}/.test('𠮷𠮷'); // false
/𠮷{2}/u.test('𠮷𠮷'); // true
第三個式子等於
/\uD842\uDFB7{2}/.test('\uD842\uDFB7\uD842\uDFB7');
加上 u
flag,讓預定義模式正確處理
/^\S$/.test('𠮷') // false
/^\S$/u.test('𠮷') // true
有些Unicode字元編碼不同,但長得幾乎一樣,例如
\u004B
= K
\u212A
= K
加上 u
flag,可識別非規範內的字元
/[a-z]/i.test('\u212A') // false
/[a-z]/iu.test('\u212A') // true
針對目標字串,只會從lastIndex
屬性指定的索引位置開始尋找
let s = 'aaa_aa_a';
let r1 = /a+/g;
let r2 = /a+/y;
r1.exec(s) // ["aaa"]
r2.exec(s) // ["aaa"]
r1.exec(s) // ["aa"]
r2.exec(s) // null
在split
方法中使用 flag y
,若匹配成功,則回傳矩陣第一個值一定為空字串
目標值必須相鄰才會被匹配成功
'#x#'.split(/#/y);// [ '', 'x#' ]
'##'.split(/#/y);// [ '', '', '' ]
使用replace方法的例子
const REGEX = /a/gy;
'aaxa'.replace(REGEX, '-'); // '--xa'
使用match
方法只能返回第一個匹配,必須與flag g
並用才能回傳所有匹配
'a1a2a3'.match(/a\d/y); // ["a1"]
'a1a2a3'.match(/a\d/gy); // ["a1", "a2", "a3"]
flag y的一個應用,是從字串中提取 token,確保每一個匹配。若有非pattern的字出現則停止匹配。
const TOKEN_Y = /\s*(\+|[0-9]+)\s*/y;
const TOKEN_G = /\s*(\+|[0-9]+)\s*/g;
tokenize(TOKEN_Y, '3x + 4');
// [ '3' ]
tokenize(TOKEN_G, '3x + 4');
// [ '3', '+', '4' ]
function tokenize(TOKEN_REGEX, str) {
let result = [];
let match;
while (match = TOKEN_REGEX.exec(str)) {
result.push(match[1]);
}
return result;
}
sticky
屬性為布林,若正則表達式物件使用flag y
則為true
let r = (/hello\d/y).sticky;
// true
flags
屬性為字串,回傳正則表達式使用的 flags
// ES5的source property
// return pattern of RegExp
let foo = /abc/ig.source;
// "abc"
// ES6的flags property
// return flags of RegExp
let bar = /abc/ig.flags;
// 'gi'
未成為ES6標準
處理需要被跳脫的特殊字元
RegExp.escape("The Quick Brown Fox"); // "The Quick Brown Fox"
RegExp.escape("Buy it. use it. break it. fix it.");
// "Buy it\. use it\. break it\. fix it\."
RegExp.escape("(*.*)"); // "\(\*\.\*\)"
未成為ES6標準
lookahead
/\d+(?=%)/.exec('100% of US presidents have been male');
// ["100"]
negative lookahead
/\d+(?!%)/.exec('that’s all 44 of them'); // ["44"]
lookbehind
/(?<=\$)\d+/.exec('Benjamin Franklin is on the $100 bill');
// ["100"]
negative lookbehind
/\d+(?!%)/.exec('that’s all 44 of them'); // ["44"]
不符合預期的行為
capturing group 內容不同
/^(\d+)(\d+)$/.exec('1053');
// ["1053", "105", "3"]
/(?<=(\d+)(\d+))$/.exec('1053');
// ["", "1", "053"]
capturing group 順序不同
/(?<=(o)d\1)r/.exec('hodor') // null
/(?<=\1d(o))r/.exec('hodor') // ["r", "o"]
使用工具