正規表示式測試
用自己的文本測試 JavaScript 正規表示式。可切換 g、i、m、s、u 標誌,檢視每個匹配的位置與捕獲組,並即時預覽替換結果。
邊輸入邊看到每一個匹配、每一個分組和每一個位置。 輸入模式和待匹配的文本。每條結果都會列出位置和捕獲組;模式非法時會顯示引擎自身的報錯資訊;替換框則精確展示一次 replace 呼叫會產生什麼。
用自己的文本測試 JavaScript 正規表示式。可切換 g、i、m、s、u 標誌,檢視每個匹配的位置與捕獲組,並即時預覽替換結果。
邊輸入邊看到每一個匹配、每一個分組和每一個位置。 輸入模式和待匹配的文本。每條結果都會列出位置和捕獲組;模式非法時會顯示引擎自身的報錯資訊;替換框則精確展示一次 replace 呼叫會產生什麼。
這五個標誌不是偏好設定,它們會重新定義整個模式。沒有 g 時,搜尋找到第一個匹配就停止;加上它,引擎會維護一個 lastIndex 游標遍歷整個字串——這也是同一個全域性正則在多次呼叫間複用時,看起來會「跳過」匹配的原因。i 標誌按 Unicode 大小寫對映摺疊大小寫,而不是簡單的 ASCII 位移。
最容易被誤解的是 m 和 s。m 只改變 ^ 和 $ 的含義,把它們錨定到行邊界而非整個字串,對 . 毫無影響;反過來 s 只改變 .,讓它能匹配換行符。記住 "dotall" 這個名字最有用。u 標誌讓模式按碼點而非 UTF-16 碼元工作,於是 . 能把一個 emoji 當作一個整體匹配,\u{1F600} 這樣的轉義也變得合法。它同時會把過去被容忍的轉義變成錯誤——這就是給已有模式加上它會突然報錯的原因。
每一對圓括號預設都會捕獲,按左括號出現的順序編號,替換時的 $1、$2 引用的正是這些編號。巢狀遵循同樣的規則,所以在 ((a)b) 中第一組是 ab,第二組是 a。當你只是為了分支或重複而需要分組時,用 (?:...) 可以不分配捕獲,也讓編號更易讀。
每個匹配所報告的位置,是首個被匹配字元的偏移量,其意義比聽上去更大。它讓你能區分位於不同位置的兩個相同匹配,確認錨點是否如預期生效,並診斷經典的零長度匹配。像 \d* 這樣的模式在任何地方都能匹配空串,於是全域性掃描會在每個位置都找到一個匹配;引擎之所以還能推進,是因為實現會在匹配為空時強制把游標前移。
包括 JavaScript 在內的多數引擎使用回溯。當模式的某一部分失敗時,引擎會退回上一個決策點嘗試另一條路徑。通常這不可見。一旦巢狀量詞讓路徑數量指數級增長,它就會變成災難,經典形態是用 (a+)+b 去匹配一長串沒有 b 的 a。這種輸入能讓瀏覽器標籤頁卡死;如果模式來自使用者輸入,它就成了拒絕服務的攻擊面。
兩個習慣幾乎能規避全部問題:優先使用具體的字元類而非 .*,以免多個分支互相重疊;能加錨點就加錨點,因為帶錨點的失敗會被立即否定,而不是在每個偏移位置重試一遍。本工具還把結果上限設為 500 條並在截斷時給出提示,這樣失控的模式只會退化為較慢的結果,而不是凍結頁面。