本篇介紹 ES2018 (ES9) 提供的 RegExp Lookbehind Assertions。
Lookarounds 是 zero-width assertions,該 assertion 與字串 match 而 consuming 任何內容。
過去 ECMAScript 有 lookahead assertions 的向前 assertions,但沒有 lookbehind assertions 提供的向後 assertions。
lookbehind assertions 分為 positive 和 negative。使用 lookbehind assertions 可以確保某個 pattern 之前有或沒有另一個 pattern,例如:可以 match 美元金額,但不 capture 美元符號。
(?<=...)
(?<=x)y
代表 x
後面若接著 y
時,才會 match y
。
可確保其中包含的 pattern 位於 assertion 之後的 pattern 之前
例如:match 美元金額而不 capture 美元符號:
let pattern = /(?<=\$)\d+(\.\d*)?/;
let match1 = pattern.exec('$59.21');
console.log(match1);
// ["59.21", ".21", index: 1, input: "$59.21", groups: undefined]
let match2 = pattern.exec('€59.21');
console.log(match2);
// null
(?<!...)
(?<=x)y
代表 x
後面不是接著 y
時,才會 match y
。
確保其中的 pattern 不位於 assertion 之後的 pattern 之前
例如:不會 match 美元金額,但會 match 歐元金額:
let pattern = /(?<!\$)\d+(?:\.\d*)/;
let match1 = pattern.exec('$9.87');
console.log(match1);
// null
let match2 = pattern.exec('€9.87');
console.log(match2);
// ["9.87", index: 1, input: "€9.87", groups: undefined]
所有 RegExp pattern,甚至是 unbounded pattern 都可作為 lookbehind assertions 的一部分。例如:可用 /(?<=\$\d+\.)\d+/
來 match 美元金額並只 capture 小數部份:
let pattern = /(?<=\$\d+\.)\d+/;
let match = pattern.exec('$59.21');
console.log(match);
// ["21", index: 4, input: "$59.21", groups: undefined]
pattern 通常從最左邊的 sub-pattern 開始 match,若左邊的 sub-pattern match 成功,就會繼續移動至右邊的 sub-pattern。當包含在 lookbehind assertion 中時,match 順序會相反。pattern 會從最右邊的 sub-pattern 開始 match,然後向左取代。
例如:/(?<=\$\d+\.)\d+/
pattern 會先找到一個數字,並確定後面接著 .
,然後 \d+
從 .
開始的,最後 $
從 assertion 中的 \d+
位置開始。所以回溯 (backtracking) 的方向也會相反。