Regex 進階用法 - Lookbehind 與 lookahead

前言 正規表達式(Regex)是文字處理中的重要工具,無論是搜尋、驗證表單還是數據清理都非常常見,或是客製化 config 檔時也能透過正則表達式設計更複雜的邏輯。 而進階技巧如 Lookbehind 和 Lookahead 則讓開發者能夠撰寫更精確的表達式。這些特性幫助我們在匹配特定內容時可以加上前後文條件,卻不將這些條件納入匹配結果中。 本文將紀錄 Lookbehind 和 Lookahead 的概念、其運作方式,並提供一些實際範例來紀錄這些進階用法。 Zero-Width Assertions 首先,在介紹 Lookahead 和 Lookbehind 這兩個表達式以前,要先知道一個叫做 Zero-Width Assertions 的概念 (中文不知道怎麼翻譯,就直接用英文表示)。 Zero-Width Assertions 是指那些僅匹配文本中的特定位置,而非具體字符的語法或表達式。 它們會在想要匹配的字串中的某個位置檢查特定條件,但不會消耗任何字符,也不會使正則表達式引擎的游標向前推進。因此,這類斷言經常被稱為「隱形」條件,能夠在不影響最終匹配結果的情況下,讓我們定義更複雜的匹配模式。 聽起來有點抽象,簡單來說概念就像是 regex 世界的 if/else,可以做一些邏輯的判定。 常見的 Zero-Width Assertions 有底下三種: Lookahead Lookbehind Anchor (^, $) 前面兩個我們先忽略,因為等等後面會一一介紹。第三個 Anchor 仔細看會發現就是我們平常在用的字串起始(^)與字串結尾($) 快速舉個例子來說, ^Helloween$ 這個表達式可以匹配到 “Helloween” 這個字串,但不會匹配到 “~Helloween” 和 “Helloween~” 這兩個字串,原因是我們明確指定字串要以 H 開頭且以 n 結尾。 當使用 Anchor 這類的 Zero-Width Assertions 表達式,並不會消耗我們的字元,意思是他只會拿來做為邏輯的判定(是否以某字元做起始? 是否以某字元做結尾?),這樣會帶來幾點好處: 可以根據上下文設定匹配的邏輯判定(某文字之前或之後),而不會影響實際匹配的內容 消除不必要的 backtracking 來避免效能的減損 (Catastrophic Backtracking) ahead vs behind 要介紹 Lookahead 和 Lookbehind 之前,要先定義到底什麼是 ahead?...

<span title='2024-10-25 18:12:13 +0800 +0800'>October 25, 2024</span>&nbsp;·&nbsp;2 min&nbsp;·&nbsp;267 words&nbsp;·&nbsp;Madi