正規表示式並非單一語言。POSIX BRE、POSIX ERE 和 Perl 相容引擎有所重疊, 但它們的語法、比對規則和可用功能並不相同。
POSIX BRE #
基本正規表示式是 grep 和 sed 採用的歷史語法。
重要規則:
- 群組使用
\(和\); - 計數重複使用
\{m,n\}; - 除非工具加入擴充功能,否則
+、?、|和()都是常值字元; - 反向參照使用
\1、\2,依此類推。
BRE 具備可攜性,但因為許多中繼字元需要跳脫,所以較為冗長。
POSIX ERE #
擴充正規表示式更接近現代正規表示式語法:
()用於群組;+表示一次或多次;?表示零次或一次;{m,n}計算重複次數;|表示替代。
grep -E 和 sed -E 使用這種形式。POSIX ERE 仍有限制,因為它不支援
惰性量詞、前瞻或後顧。
Perl 相容引擎 #
Perl 相容正規表示式增加了 POSIX RE 所沒有的功能:
*?和+?等惰性量詞;- 前瞻與後顧;
(?:...)等非擷取群組;- 許多引擎支援具名擷取;
- 更豐富的字元類別語法。
因此,非貪婪比對經常會迫使你切換引擎。POSIX BRE 和 ERE 根本沒有 等效的運算子。
比對行為 #
POSIX 引擎以最左最長比對為規範。即使語法看似相同,此規則產生的結果仍可能 與 Perl 風格引擎不同。
當替代和重複有所重疊時,這一點相當重要,因為引擎可能偏好較長的比對, 而非第一個成功的語法替代項。
錨點也取決於引擎和模式。POSIX 的 ^ 與 $ 表示字串的開頭和結尾,
各工具對行的行為則有所不同;PCRE 風格引擎通常提供獨立的絕對字串錨點和
多行模式。請明確比對常值輸入邊界,而不要假設命令的預設行為。
字元類別並非固定的 ASCII 簡寫。[[:alpha:]] 等 POSIX 方括號類別遵循
目前使用中的語系,而 \w、大小寫摺疊和 Unicode 屬性會隨 Perl 相容
實作及旗標而異。對於以位元組為導向的自動化,請設定已知語系;或明確選擇
引擎的 Unicode 模式。
對於模稜兩可的巢狀重複,回溯引擎可能耗費指數級時間,例如使用 (a+)+$
比對一段很長且不相符的輸入。處理不受信任的資料時,請限制輸入大小、避免
重疊的替代項和巢狀量詞,或使用線性時間引擎。環視和非擷取群組可以改善
運算式結構,但不會使引擎彼此相容。
實務轉換 #
相同意圖經常需要不同語法:
- 擷取群組:BRE 使用
\(...\),ERE 使用(...); - 一個或多個數字:BRE 使用
\{1,\},ERE 使用+; - 非貪婪萬用字元:POSIX RE 不支援。
需要可攜性時,請選擇特定引擎,並使用能符合任務需求的最小功能集合。 應根據預期語言和比對語意進行轉換,而非機械式地增加或移除反斜線。
評論
在 GitHub 上閱讀或評論(發表評論需要登入)