檢查 regex 的方式是將它套用到一段範例字串上,然後檢視它所產生的匹配結果、擷取群組和具名群組——而對 JavaScript 模式來說,最快的方法就是把 regex 直接輸入到 Regex Tester 的欄位中,視需要切換旗標,然後在輸入的同時閱讀下方結果中以醒目方式標示的匹配結果。

檢查正則表達式是一個「建立—測試—微調」的迴圈,而不是一次性的驗證。你寫好一個模式,拿它對具代表性的輸入進行測試,然後反覆調整,直到匹配結果和群組都完全符合預期。問題在於,不同的程式語言使用的 regex 方言略有不同,所以在 Python 中能運行的模式,在 JavaScript 中可能表現得不一樣。Regex Tester 使用瀏覽器原生的 JavaScript RegExp 引擎,這代表在這個工具中能匹配成功的模式,在 JavaScript、TypeScript 和 Node 中也會以同樣方式匹配——反之亦然。不需要安裝任何東西、不需要上傳任何東西,也不需要註冊帳號;這個工具完全在你的瀏覽器中使用本地 JavaScript 執行,所以你的模式和測試文字都會保留在你的裝置上。

how to check regex
how to check regex

Regex 檢查的三項工作

「檢查 regex」通常意味著以下三件事中的其中一項,而同一個工具就能回答這三個問題。

  • 驗證 (Validation): 這個模式是否能接受有效輸入並拒絕無效輸入?你可以用幾組正例和反例進行測試以確認。
  • 擷取 (Extraction): 這個模式是否能提取出我需要的欄位——日期、ID、價格、slug?你可以檢視擷取群組和具名群組來確認其結構。
  • 除錯 (Debugging): 為什麼我的模式什麼都沒傳回,或是傳回了錯誤的結果?你可以閱讀匹配明細,確切看出哪些字元被匹配、哪些群組有參與。

這三項任務共用同一個工作流程:輸入模式、將它指向範例文字,然後檢視引擎回報的結果。Regex Tester 就是圍繞著這個工作流程所設計,因此本指南接下來的內容會逐一說明如何針對每種情況使用它。

使用 Regex Tester 測試模式

這個介面包含三個可動元件:一個模式輸入框、一列旗標,以及一塊測試字串區域。以下是一般檢查的標準操作順序。

  1. 在 /…/ 欄位中輸入或貼上模式。 你不需要自行加上斜線——一旦你切換任何旗標,工具會自動為你加上字面常值的斜線。
  2. 切換你需要的旗標。 常見的選擇包括 g(尋找所有匹配)、i(忽略大小寫),以及當你的錨點需要在每一行都作用時使用的 m。
  3. 輸入或貼上你的測試字串。 請使用一個真實的範例,其中同時包含你希望匹配到的內容以及一些不希望匹配到的內容,這樣你才能驗證這個模式不會匹配過頭。
  4. 閱讀標示出來的匹配結果。 在你的測試字串中,每一個匹配都會就地以醒目方式標示出來,並且一個明細面板會將每個匹配逐一拆解:起始索引、完整的匹配文字、編號的擷取群組,以及任何以 (?<name>…) 撰寫的具名群組。
  5. 一次只微調一個符記。 修改一個量詞、替換一個字元類別、或新增一個錨點,並在輸入的同時觀察醒目標示如何更新——這就是對每個組件的作用建立直覺最快的方式。

如果你預期會有多個匹配,但模式卻只找到第一個,那麼最常見的原因就是忘了加 g 旗標。少了它,JavaScript 會在第一個匹配處停下來;有了它,引擎就會回報字串中所有的匹配。

JavaScript 的六個旗標及其個別用途

JavaScript 的 RegExp 建構函式提供了六個旗標,而 Regex Tester 將它們全部都開放為可切換的選項。旗標列會自動為你重建 /pattern/flags 的字面常值,讓你可以把這個完整的運算式直接複製到你的程式碼中。

旗標名稱它改變了什麼
gglobal(全域)尋找字串中所有的匹配,而不會停在第一個匹配處。
iignore case(忽略大小寫)讓字母匹配變成不區分大小寫:/abc/i 會匹配 "ABC"、"Abc" 和 "abc"。
mmultiline(多行)讓 ^ 和 $ 錨定到每一行,而不只是整個字串的開頭和結尾。
sdotAll(點匹配全部)讓「點」. 除了匹配其他任何字元外,也能匹配換行字元。
uunicode(Unicode)啟用完整的 Unicode 處理,包括代理對和 Unicode 屬性跳脫。
ysticky(黏性)只從 lastIndex 開始匹配;當你需要從左到右進行斷詞時相當實用。

在大多數日常的檢查中,你只需要 g,有時再加上 i。當你的輸入有多行,且你希望 ^…$ 能匹配每一行時,請使用 m;而當你的模式需要跨越換行字元時,則請使用 s。

閱讀匹配結果:擷取、具名群組和零寬匹配

測試字串下方的明細面板,就是你用來確認模式是否符合預期的地方。其中有三項內容值得仔細檢視。

擷取群組 就是括號內的子字串。它們會依照順序回報,從索引 1 開始,所以模式中第一個 (…) 就是第 1 群組,第二個就是第 2 群組,依此類推。如果某個群組是選用的,且在特定的匹配中沒有參與,工具會清楚地標示出來,讓你能看出為什麼一個選用群組會傳回空值。

具名群組 使用 (?<name>…) 這個語法,並且會和它們的數字位置一起回報。它們讓你可以用一個易讀的名稱而非索引來參照一個擷取結果,這在 String.match、matchAll 和 replace 的回呼函式中維護起來要容易得多。

零寬匹配 是最容易讓人卡住的地方。像 a*、^、\b 或空字串這類的模式,匹配的是一個位置而非一個字元。加上 g 旗標後,一個粗糙的迴圈對它們進行迭代時,會在同一個空位置上不斷重複匹配,最終凍結瀏覽器。這個工具會安全地越過每一個零寬匹配並回報其位置,而不會造成當機,這對用於診斷目的來說才是正確的行為。

快速 Regex 檢查的常見用途

啟動 regex 工具最常見的理由,可以歸納為以下幾個實際的類別。

  • 驗證使用者輸入。 電子郵件、電話號碼、URL 和 slug 等模式,都能透過真實和對抗性的樣本快速地製作原型。
  • 從文字中擷取欄位。 日期、ID、價格、日誌嚴重性等級等類似的符記,都容易透過具名群組進行擷取和標記。
  • 為「尋找與取代」製作原型。 先把候選模式放進這個工具測試,之後在 String.replace 或 replaceAll 中使用相同的運算式時就不會出現意外。
  • 學習基本構成要素。 字元類別(\d、\w、\s 以及它們的反向形式)、量詞(*、+、?、{n,m})、錨點(^、$)、交替(|)和 lookahead((?=…)、(?!…)),都可以透過一次改變一個符記、觀察醒目標示如何更新的方式來學習。

有一點效能上的注意事項值得記住:一個撰寫不佳的模式,可能會在某些輸入上引發災難性回溯——這是一種 ReDoS(正則表達式拒絕服務)的形式。在這個工具內部,這頂多只會拖慢你自己瀏覽器分頁的速度;沒有任何東西在伺服器上執行,也沒有任何東西被上傳。在正式的程式碼中,實務上的重點是為你的模式加上錨點,並避免在不受信任的輸入上使用巢狀量詞。

值得優先嘗試的 Regex 基本構成要素

如果你仍在學習語法,這個工具同時也是一個練習場。透過輸入並觀察以下簡短的符記清單,就足以建立起可用的心智模型。

符記它匹配什麼用什麼來試試
\d任何數字,0–9"Order #4729 confirmed"
\w任何「文字」字元(字母、數字、底線)"user_name-42"
\s任何空白字元含有空格和定位字元的多行輸入
^ 和 $一行的開頭與結尾(搭配 m 時),或字串的開頭與結尾像 "BEGIN" 和 "END" 這樣的行
{n,m}n 到 m 次的重複特定長度的單字
(?=…)正向 lookahead——進行斷言但不消耗字元密碼規則和價格後綴

若想取得一份更完整的、屬於 JavaScript 方言的符記清單,在你實驗的過程中,Regex Cheat Sheet 是一份很實用的輔助參考資料。

無論你最後寫出什麼模式,只要在 Regex Tester 中確認一次,你就能把同樣的 /pattern/flags 字面常值原封不動地放進 String.match、matchAll、replace 或 RegExp 建構函式中——因為兩者所用的引擎是完全相同的。

如果你正在權衡各種選項,How to Generate UUIDs in JavaScript 對此有詳細的說明。

如果你正在權衡各種選項,Parse Query Strings in JavaScript the Browser-Native Way 對此有詳細的說明。