正規表示式速查表

面向 JavaScript 方言的可搜尋正則速查表:字元類、方括號集合、量詞、錨點、環視、分組與標誌位,每條都配有示例。

41 條正則語法,條條帶示例。 在記號、說明和示例中同時篩選,找到需要的語法直接複製。內容以瀏覽器與 Node.js 使用的 JavaScript(ECMAScript)方言為準。

自信地讀寫正規表示式

這是一張語法表,而不是教程

正規表示式天生就寫得很密。^(?:\d{1,3}\.){3}\d{1,3}$ 這樣一個模式,用三十來個字元就塞進了一個完整的 IPv4 校驗器——自己寫的時候很爽,讀別人寫的時候很痛苦。難點其實大多不在概念,而在於這套詞彙量大、寫法簡短,且極容易記個半吊子。

本頁就是這套詞彙的查詢表,按照實際構建模式的順序組織:匹配單個字元的寫法、如何自定義字元集合、如何表達「重複若干次」、在哪裡加錨點、怎樣分組與選擇,以及哪些標誌位會改變引擎行為。篩選框會同時搜尋記號、說明和示例,因此輸入「惰性」「boundary」或「lookbehind」都能直接跳到你記了一半的那一行。

這些記號遵循哪種方言

正規表示式並不是一種統一的語言。grep、PCRE、Python、Java、Go 的 RE2 和 JavaScript 共享一個核心,但在細節上各不相同。這裡列出的全部內容都以 ECMAScript 定義的 JavaScript 方言為準,因為那正是瀏覽器、Node.js 和絕大多數前端工具鏈所執行的方言。

有三處差異值得特別提醒。第一,後行斷言 (?<=...)(?<!...) 在現代 JavaScript 引擎中受支援,但 Go 的 RE2 和較舊版本的 Safari 並不支援,因此依賴它的模式並非處處可移植。第二,JavaScript 沒有 x 詳細模式標誌,無法像 Python 那樣把模式拆成多行並加註釋;較長的模式通常改用字串片段拼接而成。第三,JavaScript 中的 \d\w 預設只覆蓋 ASCII,因此 \w 不會匹配帶重音的字母或中日韓字元,除非配合 u 標誌改用 \p{L} 這類 Unicode 屬性轉義。

寫出可維護的模式

兩個習慣能避免絕大多數正則相關的痛苦。第一是有意識地加錨點。沒有錨點的模式會在字串的任意位置尋找匹配——掃描文本時這正是你要的,但做校驗時幾乎從來不是。加上 ^$,就把「包含某個看起來像日期的片段」變成了「本身就是一個日期」,而這條區別背後藏著相當比例的校驗缺陷。

第二是優先使用惰性量詞和排除型字元類,而不是貪婪通配。經典錯誤是在類 HTML 文本上寫 <.+>:由於 + 是貪婪的,它會一路吞到該行最後一個 >。寫成 <.+?>,或者更好的 <[^>]+>,才只匹配單個標籤。排除型字元類的版本還明顯更快,因為引擎完全不需要回溯。

最後要留意災難性回溯。像 (a+)+b 這樣巢狀量詞,可能讓引擎在得出「不匹配」結論之前,先嚐試指數級數量的切分方式;一旦這種模式接觸使用者輸入,一次校驗呼叫就變成了拒絕服務的攻擊面。如果模式裡有一個帶量詞的分組、內部又含量詞,就應該重寫它——通常改成「一個字元類加一個量詞」就能線上性時間內完成同樣的工作。而當模式長到超過一兩行時,坦白講,正確的工具往往是一個真正的解析器,而不是正則。

自研實現。語法表以 JavaScript(ECMAScript)正則方言為準,全部邏輯都在你的瀏覽器中執行。

常見問題

這些記號描述的是哪種正則方言?
是 JavaScript(ECMAScript)方言,也就是瀏覽器、Node.js 和絕大多數前端工具鏈所使用的方言。其核心語法與 PCRE、Python、Java 相通,因此絕大部分記號可以直接遷移;但如果目標是其他引擎,請單獨確認後行斷言和 Unicode 屬性轉義的支援情況。
為什麼我的模式匹配到的內容比預期多?
幾乎總是因為量詞是貪婪的。* 和 + 會盡可能多地吞掉字元,只有當後續部分匹配失敗時才逐個吐回。加上 ? 變成惰性(如 .+?),或者用排除型字元類替換萬用字元(如 [^>]+),後者既更精確也更快。
捕獲組和非捕獲組有什麼區別?
(abc) 會儲存匹配到的內容,之後可以用 \1 引用,或從結果陣列中讀取;(?:abc) 只是把記號組合起來以便施加量詞或選擇,不儲存任何內容。當你只需要分組時請用非捕獲形式,它能讓結果下標保持穩定,開銷也略低。
為什麼 \w 匹配不到帶重音的字母或中文?
在 JavaScript 中 \w 被定義為 [A-Za-z0-9_],刻意只覆蓋 ASCII。要匹配任意文字體系的字母,請配合 u 標誌使用 Unicode 屬性轉義:/\p{L}+/u 可以匹配拉丁、西里爾、希臘、漢字、假名等所有字母。
正規表示式會帶來安全風險嗎?
會。像 (a+)+b 這樣的巢狀量詞可能觸發災難性回溯,引擎在判定失敗前會嘗試指數級數量的可能性。如果這類模式作用在使用者輸入上,一段精心構造的短字串就能讓程序卡死。請儘量把巢狀量詞改寫為單個字元類。
可以用正則解析 HTML 或 JSON 嗎?
不建議。兩者都是可遞迴巢狀的格式,而正規表示式無法表達任意深度的巢狀。請使用真正的解析器:HTML 用 DOMParser,JSON 用 JSON.parse。正則更適合掃描扁平文本、校驗簡單欄位格式,以及做定向查詢替換。