">"> ">
2020 年 5 月 19 日

模式中的反向引用:\N 和 \k<name>

我們不僅可以在結果或替換字串中使用擷取群組 (...) 的內容,還可以在模式本身中使用。

依據數字進行反向引用:\N

可以使用 \N 在模式中參照群組,其中 N 是群組編號。

為了清楚說明為什麼這很有用,我們來考慮一個任務。

我們需要找出帶引號的字串:單引號 '...' 或雙引號 "..." – 兩種變體都應該符合。

如何找出它們?

我們可以將兩種引號都放在方括號中:['"](.*?)['"],但它會找出帶有混合引號的字串,例如 "...''..."。當一個引號出現在另一個引號內時,這將導致不正確的比對,例如在字串 "She's the one!"

let str = `He said: "She's the one!".`;

let regexp = /['"](.*?)['"]/g;

// The result is not what we'd like to have
alert( str.match(regexp) ); // "She'

如我們所見,模式找到一個開啟引號 ",然後文字會被消耗到另一個引號 ',它會關閉匹配。

為了確保模式尋找的關閉引號與開啟引號完全相同,我們可以將它包進一個擷取群組並反向參照它:(['"])(.*?)\1

以下是正確的程式碼

let str = `He said: "She's the one!".`;

let regexp = /(['"])(.*?)\1/g;

alert( str.match(regexp) ); // "She's the one!"

現在它運作了!正規表示式引擎會找到第一個引號 (['"]) 並記住它的內容。那是第一個擷取群組。

在模式中的 \1 表示「找到與第一個群組中相同的文字」,在我們的例子中就是完全相同的引號。

類似地,\2 表示第二個群組的內容,\3 表示第三個群組,以此類推。

請注意

如果我們在群組中使用 ?:,那麼我們就無法參照它。從擷取中排除的群組 (?:...) 沒有被引擎記住。

不要搞混:在模式中的 \1,在替換中的:$1

在替換字串中我們使用美元符號:$1,而在模式中則使用反斜線 \1

按名稱反向參照:\k<name>

如果一個正規表示式有很多括號,那麼給它們命名會很方便。

為了參照一個命名群組,我們可以使用 \k<name>

在下面的範例中,帶有引號的群組被命名為 ?<quote>,所以反向參照是 \k<quote>

let str = `He said: "She's the one!".`;

let regexp = /(?<quote>['"])(.*?)\k<quote>/g;

alert( str.match(regexp) ); // "She's the one!"
教學課程地圖

留言

在留言前先閱讀這段…
  • 如果你有建議要如何改進 - 請 提交 GitHub 議題 或提交 pull request,而不是留言。
  • 如果你無法理解文章中的某個部分 - 請詳細說明。
  • 若要插入幾行程式碼,請使用 <code> 標籤,若要插入多行程式碼,請將它們包在 <pre> 標籤中,若要插入超過 10 行的程式碼,請使用沙盒 (plnkrjsbincodepen…)