快速入門
教學
工具和語言
範例
參考
書籍評論
正規表示式工具
grep
PowerGREP
RegexBuddy
RegexMagic
一般應用程式
EditPad Lite
EditPad Pro
語言和函式庫
Boost
Delphi
GNU (Linux)
Groovy
Java
JavaScript
.NET
PCRE (C/C++)
PCRE2 (C/C++)
Perl
PHP
POSIX
PowerShell
Python
R
Ruby
std::regex
Tcl
VBScript
Visual Basic 6
wxWidgets
XML Schema
Xojo
XQuery 和 XPath
XRegExp
資料庫
MySQL
Oracle
PostgreSQL
此網站的更多資訊
簡介
正規表示式快速入門
正規表示式教學
替換字串教學
應用程式和語言
正規表示式範例
正規表示式參考
替換字串參考
書籍評論
可列印 PDF
關於此網站
RSS Feed 和部落格
RegexBuddy—The best regex editor and tester for Python developers!

Python 的 re 模組

Python 是一種高階開源指令碼語言。Python 內建的「re」模組提供優異的 正規表示式 支援,具備現代且完整的正規表示式風格。Python 3.11 新增了兩個重要的遺失功能,原子群組獨佔量詞。雖然 Python 的正規表示式引擎可以正確處理 Unicode 字串,但其語法仍缺少 Unicode 屬性,而 簡寫字元類別 也只會比對 ASCII 字元。

首先,使用 import re 將 regexp 模組匯入您的指令碼。

正規表示式搜尋和比對

呼叫 re.search(regex, subject) 以將正規表示式樣式套用至主旨字串。如果比對嘗試失敗,函式會傳回 None,否則會傳回 Match 物件。由於 None 會評估為 False,因此您可以在 if 陳述式中輕鬆使用 re.search()Match 物件會儲存正規表示式樣式比對到的字串部分的詳細資料。

您可以透過將特殊常數指定為 re.search() 的第三個參數,來設定 正規表示式比對模式re.Ire.IGNORECASE 會不區分大小寫地套用樣式。 re.Sre.DOTALL 會讓 點號比對換行符號re.Mre.MULTILINE 會讓 插入符號和美元符號 在主旨字串中比對換行符號前後。單字母選項和描述性選項之間沒有差異,除了您必須輸入的字元數。若要指定多個選項,請使用 | 算子將它們「或」起來:re.search("^a", "abc", re.I | re.M)

預設情況下,Python 的正規表示式引擎只將字母 A 到 Z、數字 0 到 9 以及底線視為「字元字元」。指定旗標 re.Lre.LOCALE 以使 \w 比對所有根據目前區域設定視為字母的字元。或者,您可以指定 re.Ure.UNICODE 以將所有字元的字母視為字元字元。此設定也會影響 字元邊界

不要將 re.search()re.match() 混淆。這兩個函式執行完全相同的動作,重要的區別在於 re.search() 會在字串中嘗試比對樣式,直到找到符合的結果。另一方面,re.match() 只會在字串的開頭嘗試比對樣式。基本上,re.match("regex", subject)re.search("\Aregex", subject) 相同。請注意,re.match() 並不要求 正規表示式與整個字串相符。re.match("a", "ab") 會成功。

Python 3.4 新增一個新的 re.fullmatch() 函式。此函式只有在正規表示式完全與字串相符時才會傳回 Match 物件。否則,它會傳回 Nonere.fullmatch("regex", subject)re.search("\Aregex\Z", subject) 相同。這對於驗證使用者輸入很有用。如果 subject 是空字串,則對於任何可以找到 零長度比對 的正規表示式,fullmatch() 會評估為 True

若要從字串取得所有比對結果,請呼叫 re.findall(regex, subject)。這會傳回一個陣列,其中包含字串中所有不重疊的正規表示式比對結果。「不重疊」表示字串從左到右搜尋,而下一個比對嘗試會從前一個比對結果之後開始。如果正規表示式包含一個或多個 擷取群組re.findall() 會傳回一個陣列,其中每個陣列元素都包含由所有擷取群組比對到的文字。整體正規表示式比對結果不會包含在陣列元素中,除非您將整個正規表示式置於擷取群組中。

re.findall() 更有效率的是 re.finditer(regex, subject)。它會傳回一個反覆運算器,讓您可以在主旨字串中的正規表示式比對結果中進行迴圈:for m in re.finditer(regex, subject)。for 迴圈變數 mMatch 物件,其中包含目前比對結果的詳細資料。

re.search()re.match() 不同,re.findall()re.finditer() 不支援使用正規表示式比對旗標的第三個選用參數。相反地,您可以在正規表示式的開頭使用 全域模式修改器。例如,「(?i)regex」比對 regex 時不區分大小寫。

字串、反斜線和正規表示式

反斜線是正規表示式中的元字元。它用於跳脫其他元字元。正規表示式 \\ 符合單一反斜線。 \d單一記號,符合數字。

Python 字串也使用反斜線來跳脫字元。上述正規表示式寫成 Python 字串為 "\\\\""\\d"。確實令人混淆。

幸運的是,Python 也有「原始字串」,不會對反斜線套用特殊處理。作為原始字串,上述正規表示式變成 r"\\"r"\d"。使用原始字串的唯一限制是,用於字串的分隔符號不能出現在正規表示式中,因為原始字串沒有提供跳脫它的方法。

你可以在原始字串中使用 \n 和 \t。儘管原始字串不支援這些跳脫,但正規表示式引擎支援。最終結果是一樣的。

Unicode

在 Python 3.3 之前,Python 的 re 模組不支援任何Unicode 正規表示式記號。然而,Python Unicode 字串一直支援 \uFFFF 表示法。Python 的 re 模組可以使用 Unicode 字串。因此,你可以將 Unicode 字串 u"\u00E0\\d" 傳遞給 re 模組,以符合 à 後接數字。 \d 的反斜線已跳脫,而 \u 的反斜線則沒有。這是因為 \d 是正規表示式記號,而正規表示式反斜線需要跳脫。 \u00E0 是不應跳脫的 Python 字串記號。正規表示式引擎將字串 u"\u00E0\\d" 視為 à\d

如果你在 \u 前面再放一個反斜線,正規表示式引擎會看到 \u00E0\d。如果你在 Python 3.2 或更早版本中使用這個正規表示式,它將符合文字 u00E0 後接數字。

為了避免混淆反斜線是否需要跳脫,請使用 Unicode 原始字串,例如 ur"\u00E0\d"。這樣反斜線就不需要跳脫。Python 會在原始字串中詮釋 Unicode 跳脫。

在 Python 3.0 和更新版本中,字串預設為 Unicode。因此,上述範例中顯示的 u 前綴不再需要。Python 3.3 也為正規表示式引擎新增支援 \uFFFF 表示法。因此,在 Python 3.3 中,您可以使用字串 "\\u00E0\\d" 來傳遞 regex \u00E0\d,它會比對類似 à0 的字串。

搜尋和取代

re.sub(regex, replacement, subject) 在 subject 中執行搜尋和取代,將 subject 中所有 regex 比對結果取代為 replacement。結果由 sub() 函式傳回。您傳遞的 subject 字串不會被修改。

如果 regex 有 擷取群組,您可以使用 regex 中擷取群組內部分比對的文字。若要取代第三個群組的文字,請在 replacement 字串中插入 \3。如果您想要使用第三個群組的文字,後面加上一個文字三作為取代字串,請使用 \g<3>3\33 會被解釋為第 33 個群組。如果群組少於 33 個,則會發生錯誤。如果您使用 命名擷取群組,則可以在 replacement 文字中使用 \g<name>

re.sub() 函式對 replacement 文字套用與正規表示式相同的反斜線邏輯。因此,您應該對 replacement 文字使用原始字串,就像我在上述範例中所做的那樣。 re.sub() 函式也會在原始字串中解釋 \n 和 \t。如果您想要 c:\temp 作為取代字串,請使用 r"c:\\temp""c:\\\\temp"。第三個反向參照是 r"\3""\\3"

分割字串

re.split(regex, subject) 傳回一個字串陣列。陣列包含 subject 中所有 regex 比對結果之間的 subject 部分。相鄰的 regex 比對結果會導致陣列中出現空字串。regex 比對結果本身不會包含在陣列中。如果 regex 包含 擷取群組,則擷取群組比對的文字會包含在陣列中。擷取群組會插入在出現在 regex 比對結果左邊和右邊的子字串之間。如果您不想要陣列中的擷取群組,請將它們轉換為 非擷取群組re.split() 函式沒有提供抑制擷取群組的選項。

您可以指定一個額外的第三個參數來限制分割 subject 字串的次數。請注意,此限制控制分割的次數,而不是陣列中最終會出現的字串數。未分割的 subject 餘數會新增為陣列中的最後一個字串。如果沒有擷取群組,則陣列將包含 limit+1 個項目。

當正規表示式可以找到長度為 0 的比對時,re.split() 的行為在不同版本的 Python 中有所改變。在 Python 3.4 及更早版本中,re.split() 會忽略長度為 0 的比對。在 Python 3.5 和 3.6 中,re.split() 在遇到長度為 0 的比對時會擲出 FutureWarning。這個警告表示 Python 3.7 中的變更。現在 re.split() 也會對長度為 0 的比對進行分割。

比對詳細資料

re.search()re.match() 會傳回一個比對物件,而 re.finditer() 會產生一個反覆器,用於反覆處理比對物件。這個物件包含許多關於正規表示式比對的有用資訊。以下的討論中,我將使用 m 來表示比對物件。

m.group() 會傳回與整個正規表示式比對的字串部分。 m.start() 會傳回比對開始處在字串中的偏移量。 m.end() 會傳回比對結束後一個字元的偏移量。 m.span() 會傳回 m.start()m.end() 的 2 元組。您可以使用 m.start()m.end() 來切片主旨字串:subject[m.start():m.end()]

如果您想要擷取群組的結果,而不是整體正規表示式比對,請指定群組的名稱或編號作為參數。 m.group(3) 會傳回由第三個 擷取群組 比對的文字。 m.group('groupname') 會傳回由 命名群組 'groupname' 比對的文字。如果群組未參與整體比對,m.group() 會傳回空字串,而 m.start()m.end() 會傳回 -1。

如果您想要執行基於正規表示式的搜尋和取代,而不使用 re.sub(),請呼叫 m.expand(replacement) 來計算取代文字。這個函式會傳回已取代反向參照等的取代字串。

正規表示式物件

如果您想要重複使用相同的正規表示式,您應該將其編譯成正規表示式物件。正規表示式物件更有效率,並讓您的程式碼更具可讀性。若要建立一個,只需呼叫 re.compile(regex)re.compile(regex, flags)。flags 是上面針對 re.search()re.match() 函式描述的比對選項。

re.compile() 傳回的正規表示式物件提供 re 模組也直接提供的全部函式:search()match()findall()finditer()sub()split()。不同之處在於它們使用儲存在 regex 物件中的樣式,且不將 regex 作為第一個參數。re.compile(regex).search(subject) 等同於 re.search(regex, subject)

| 快速入門 | 教學 | 工具與語言 | 範例 | 參考 | 書籍評論 |

| grep | PowerGREP | RegexBuddy | RegexMagic |

| EditPad Lite | EditPad Pro |

| Boost | Delphi | GNU (Linux) | Groovy | Java | JavaScript | .NET | PCRE (C/C++) | PCRE2 (C/C++) | Perl | PHP | POSIX | PowerShell | Python | R | Ruby | std::regex | Tcl | VBScript | Visual Basic 6 | wxWidgets | XML Schema | Xojo | XQuery 與 XPath | XRegExp |

| MySQL | Oracle | PostgreSQL |