# `re` --- 正規表示式 (regular expression) 操作

原始碼： Lib/re/

此模組提供類似於 Perl 中正規表示式的匹配操作。

被搜尋的模式 (pattern) 與字串可以是 Unicode 字串 (`str`)，也可以是 8-bit 字串 (`bytes`)。然而，Unicode 字串和 8-bit 字串不能混用：也就是，你不能用 byte 模式匹配 Unicode 字串，反之亦然；同樣地，替換時，用來替換的字串必須與模式和搜尋字串是相同的型別 (type)。

正規表示式使用反斜線字元 (`'\'`) 表示特別的形式，或是使用特殊字元而不觸發它們的特殊意義。這與 Python 在字串文本 (literal) 中，為了相同目的使用同一個字元的做法相衝突；舉例來說，為了匹配一個反斜線字面值，可能需要寫 `'\\\\'` 當作模式字串，因為正規表示式必須是 `\\`，而且每個反斜線在一個普通的 Python 字串文本中必須表示為 `\\`。另外，請注意在 Python 的字串文本中使用反斜線的任何無效跳脫序列目前會產生一個 `SyntaxWarning`，而在未來這會變成一個 `SyntaxError`。儘管它對正規表示式是一個有效的跳脫序列，這種行為也會發生。

解決方法是對正規表示式模式使用 Python 的原始字串符號；反斜線在一個以 `'r'` 為前綴的字串文本中不會被用任何特別的方式處理。所以 `r"\n"` 是一個兩個字元的字串，包含 `'\'` 和 `'n'`，同時 `"\n"` 是一個單個字元的字串，包含一個換行符號。通常模式在 Python 程式中會使用這個原始字串符號表示。

請務必注意到大部分的正規表示式操作是可以在模組層級的函式和 compiled regular expressions 中的方法使用的。這些函式是個捷徑且讓你不需要先編譯一個正規表示式物件，但是會缺少一些微調參數。

也參考

第三方的 regex 模組，有著和標準函式庫 `re` 模組相容的 API，但是提供額外的功能以及更完整的 Unicode 支援。

## Regular expression syntax

一個正規表示式（或 RE）會指定一組匹配它的字串；這個模組的函式讓你可以檢查一個特定的字串是否匹配給定的正規表示式（或是給定的正規表示式是否匹配特定的字串，說到底是一樣的）。

正規表示式可以被連接 (concatenated) 成新的正規表示式；如果 A 和 B 都是正規表示式，則 AB 也是一個正規表示式。一般來說，如果一個字串 p 與 A 匹配，並且另一個字串 q 與 B 匹配，則字串 pq 會匹配 AB。或：這在以下情況下不成立：A*或 *B 包含低優先順序的運算子；或 A 和 B 之間的邊界條件 (boundary conditions)；或是有編號群組 (numbered group) 的參照。因此，複雜的正規表示式可以輕鬆地從此處提到的簡單原始正規表示式建立。關於正規表示式的理論和實作，請參考 Friedl 書 [Frie09]，或任何有關建構編譯器的書籍。

一個簡短的正規表示式格式解釋如下。如需更多資訊或以較平易的方式了解，請參閱 如何使用正規表示式。

正規表示式可以包含特殊和一般字元。大多數一般字元，如 `'A'`、`'a'` 或 `'0'` 是最簡單的正規表示式；它們只匹配它們自己。你可以連接一般字元，讓 `last` 匹配字串 `'last'`。（在本節的其餘部分，我們會用通常沒有引號的 `這種特殊樣式` 來書寫正規表示式，而被匹配的字串會 `'在單引號中'`。）

某些字元是特殊的，像 `'|'` 或 `'('`。特殊字元會代表一般字元的類別，或是會影響它們周圍正規表示式的解讀方法。

重複運算子或量詞 (quantifiers)（`*`, `+`, `?`, `{m,n}` 等）不能直接嵌套使用。這樣避免了和非貪婪修飾符號後綴 `?` 和其他實作中的修飾符號的模糊性。要在一個重複正規表示式內添加第二個重複，可以使用括號。例如：正規表示式 `(?:a{6})*` 會匹配任何六的倍數個 `a` 字元。

特殊字元包含：

`.`

  （點） 在預設模式下，這會匹配除換行符號外的任何字元。如果指定了 `DOTALL` 旗標，這會匹配包含換行符號的任何字元。無論旗標為何，`(?s:.)` 都會匹配任何字元。

`^`

  （插入符號） 會匹配字串的開頭，並且在 `MULTILINE` 模式下，也會立即匹配緊接在每個換行符號之後的位置。

`$`

  匹配字串的結尾或是字串結尾的換行符號之前，並且在 `MULTILINE` 模式下會匹配換行符號之前的位置。`foo` 會匹配 'foo' 和 'foobar'，而正規表示式 `foo$` 只會匹配 'foo'。更有趣的是，在 `'foo1\nfoo2\n'` 中搜尋 `foo.$`，正常情況下會匹配 'foo2'，但是在 `MULTILINE` 模式下會匹配 'foo1'；在 `'foo\n'` 中搜尋單一個 `$` 會找到兩個（空的）匹配：一個在換行符號之前，一個在字串結尾。

`*`

  使得到的正規表示式匹配前面正規表示式的 0 或多次的重複，盡可能多次的重複。`ab*` 會匹配 'a'、'ab'，或後面跟著任何數量個 'b' 的 'a'。

`+`

  使得到的正規表示式匹配前面正規表示式的 1 或多次的重複。`ab+` 會匹配後面跟著任何非零數量個 'b' 的 'a'；它不會匹配 'a'。

`?`

  使得到的正規表示式匹配前面正規表示式的 0 或 1 次的重複。`ab?` 會匹配 'a' 或 'ab'。

`*?`, `+?`, `??`

  量詞 (quantifier) `'*'`、`'+'` 和 `'?'` 都是 greedy（貪婪的）；它們會盡可能地匹配更多文字。有時候這種行為不是預期的；如果正規表示式 `<.*>` 被用來匹配 `'<a> b <c>'`，它會匹配整個字串，而不只是 `'<a>'`。在量詞後添加 `?` 會讓他以 non-greedy（非貪婪的）或 minimal（最小的）方式進行匹配；盡可能匹配更少的字元。使用正規表示式 `<.*?>` 只會匹配到 `'<a>'`。

`*+`, `++`, `?+`

  類似於量詞 `'*'`、`'+'` 和 `'?'`，添加了 `'+'` 的量詞也會盡可能多次的匹配。然而，不同於真正的貪婪量詞，這些量詞在接續的正規表示式匹配失敗時不允許回溯 (back-tracking)。這些量詞被稱為 possessive （佔有的）量詞。例如，`a*a` 會匹配 `'aaaa'`，因為 `a*` 會匹配全部 4 個 `'a'`，但是在遇到最後的 `'a'` 時，此正規表示式會回溯，以讓 `a*` 最終可以總共匹配 3 個 `'a'`，而第四個 `'a'` 會被最後的 `'a'` 匹配。然而，當 `a*+a` 被用來匹配 `'aaaa'` 時， `a*+` 會匹配全部 4 個 `'a'`，但是當最終的 `'a'` 在尋找更多字元匹配失敗時，此正規表示式不能回溯並會因此匹配失敗。`x*+`、`x++` 和 `x?+` 分別等同於 `(?>x*)`、`(?>x+)` 和 `(?>x?)`。

  在 3.11 版被加入.

`{m}`

  指定應該恰好匹配 m 個前面的正規表示式；太少的匹配會造成整個正規表示式匹配失敗。例如，`a{6}` 會匹配恰好六個 `'a'` 字元，但不匹配五個。

`{m,n}`

  使得到的正規表示式重複匹配前面的正規表示式 m 到 n 次，並嘗試盡可能多次的匹配。例如，`a{3,5}` 會匹配 3 到 5 個 `'a'` 字元。忽略 m 會指定下限為零，且忽略 n 會指定無限大的上限。舉例來說，`a{4,}b` 會匹配 `'aaaab'` 或一千個 `'a'` 字元加上一個 `'b'`，但是不匹配 `'aaab'`。不可以忽略逗號，否則量詞會與前述的形式混淆。

`{m,n}?`

  使得到的正規表示式重複匹配前面的正規表示式 m 到 n 次，嘗試盡可能更少次的匹配。這是上一個量詞的非貪婪版本。例如，對六個字元的字串 `'aaaaaa'`，`a{3,5}` 會匹配 5 個 `'a'` 字元，而 `a{3,5}?` 只會匹配 3 個字元。

`{m,n}+`

  Causes the resulting RE to match from m to n repetitions of the preceding RE, attempting to match as many repetitions as possible without establishing any backtracking points. This is the possessive version of the quantifier above. For example, on the 6-character string `'aaaaaa'`, `a{3,5}+aa` attempts to match 5 `'a'` characters, then, requiring 2 more `'a'`s, will need more characters than available and thus fail, while `a{3,5}aa` will match with `a{3,5}` capturing 5, then 4 `'a'`s by backtracking and then the final 2 `'a'`s are matched by the final `aa` in the pattern. `x{m,n}+` is equivalent to `(?>x{m,n})`.

  在 3.11 版被加入.

`\`

  用來跳脫特殊字元（允許你匹配如 `'*'`、`'?'` 等字元），或是表示一個特殊序列；特殊序列將在下方討論。

  如果你沒有使用原始字串來表示正規表示式，請記得 Python 也會使用反斜線作為字串文本的跳脫序列；如果 Python 的剖析器辨認不出該跳脫序列，反斜線和接續的字元將會被包含在得到的字串中。然而，如果 Python 能辨認出該序列，反斜線應該要被重複兩次。這很複雜並且難以理解，所以強烈建議，除了最簡單的正規表示式，都應該使用原始字串。

`[]`

  用來表示一個字元集合。在一個集合中：

  - 字元可以獨立列出，例如： `[amk]` 會匹配 `'a'`、`'m'` 或 `'k'`。

  - 可以透過給定兩個字元並且使用 `'-'` 分隔它們來表示一個範圍的字元，例如 `[a-z]` 會匹配任何 ASCII 小寫字母，`[0-5][0-9]` 會匹配所有從 `00` 到 `59` 的兩位數字，而 `[0-9A-Fa-f]` 會匹配任何十六進位數字。如果 `-` 被跳脫了（如： `[a\-z]`） 或是放在第一或最後一個位置（如： `[-a]` 或 `[a-]`），它將會匹配字面的 `'-'`。

  - 除反斜線外的特殊字元會在集合內失去它們的特殊意義。例如，`[(+*)]` 會匹配任何字面字元 `'('`、`'+'`、`'*'`，或 `')'`。

  - 反斜線可能用於跳脫集合內具有特殊意義的字元，像是 `'-'`、`']'`、`'^'` 和 `'\\'` 本身，或是表示一個代表單一字元的特殊序列，像是 `\xa0` 或 `\n` 或一個字元類別，如 `\w` 或 `\S`（定義如下）。請注意，`\b` 代表單一個 "backspace" 字元，而不是在集合外代表的字元邊界，且像是 `\1` 的數值跳脫總是代表八進位數字的跳脫，而不是群組的參照。不匹配單一字元的特殊序列是不被允許的，像是 `\A` 和 `\Z`。

  - 不在範圍內的字元可以透過取集合的補集 (complement) <complementing> 匹配。如果集合中的第一個字元是 `'^'`，所有不在集合內的字元都會被匹配。例如， `[^5]` 會匹配任何除了 `'5'` 的字元，而 `[^^]` 會匹配任何除了 `'^'` 的字元。如果 `^` 不是集合中的第一個字元的話，沒有特殊意義。

  - 要在集合中匹配字面的 `']'`，在前面加上一個反斜線，或是將它放在集合中的最前面。例如，`[()[\]{}]` 和 `[]()[{}]` 都會匹配右方括號、左方括號、花括號和括號。

  - 未來可能會支援 Unicode Technical Standard #18 中的嵌套集合與集合操作。這會改變語法，所以為了促進這個改變，暫時會在模糊的情況下引發 `FutureWarning`。包含了以字面 `'['` 開頭，或是包含字面的字元序列 `'--'`、`'&&'`、`'~~'` 和 `'||'` 的集合。為了避免警告，請用反斜線跳脫它們。

  在 3.7 版的變更: 如果一個字元集合包含了其語義未來會被改變的結構，`FutureWarning` 會被引發。

`|`

  `A|B`，其中 A 和 B 可以為任何正規表示式，會創造出一個匹配 A 或是 B 的正規表示式。任何數量的正規表示式可以像這樣用 `'|'` 分隔。這也可以用在群組（見下文）中。當目標字串被掃描時，被 `'|'` 分隔的正規表示式會被從左到右嘗試。當一個模式完全匹配時，那條分支就被接受了。這代表一旦 A 匹配了，B 就不會被進一步測試，就算它會讓整個匹配更長。換句話說，`'|'` 永遠不是貪婪的。要匹配字面的 `'|'`，使用 `\|`，或是將它包圍在一個字元類別中，就像 `[|]`。

`(...)`

  匹配括號中的任何正規表示式，並且表示一個群組的開始和結束；群組的內容可以在執行匹配後取得，並且在後續的字串可以使用 `\number` 特殊序列來匹配，如下所述。要匹配字面的 `'('` 或 `')'`，用 `\(` 或 `\)`，或是將它們包圍在一個字元類別中： `[(`、`[)]`。

`(?...)`

  這是一個擴充表示法（否則一個 `'?'` 接著一個 `'('` 是沒有意義的）。`'?'` 後面的第一個字元決定了這個結構的意義和進一步的語法。擴充通常不會創造新的群組；`(?P<name>...)` 是這個規則的唯一例外。以下是目前支援的擴充。

`(?aiLmsux)`

  （集合 `'a'`、`'i'`、`'L'`、`'m'`、`'s'`、`'u'`、 `'x'` 中的一或多個字母。）該群組會匹配空字串；這些字母會為整個正規表示式設定對應的旗標。

  - `re.A`（僅限 ASCII 字元匹配）

  - `re.I`（忽略大小寫）

  - `re.L`（依賴區域設定）

  - `re.M`（多行）

  - `re.S`（點會匹配所有字元）

  - `re.U`（匹配 Unicode）

  - `re.X`（詳盡模式）

  （這些旗標在 Module contents 中說明。）如果你想將旗標當作正規表示式的一部分，而不是傳遞一個 flag 引數給 `re.compile()` 函式的話，這會有幫助。旗標應該首先在正規表示式字串中使用。

  在 3.11 版的變更: 此結構只能用於正規表示式的開頭。

`(?:...)`

  一個非捕捉版本的普通括號。匹配括號內的任何正規表示式，但是被群組匹配到的子字串不能在執行匹配後被取得，或是在之後的模式中被參照。

`(?aiLmsux-imsx:...)`

  （集合 `'a'`、`'i'`、`'L'`、`'m'`、`'s'`、`'u'`、`'x'` 中的零或多個字母，選擇性地接著 `'-'`，並接著一或多個 `'i'`、`'m'`、`'s'`、`'x'` 中的字母。）該字母集合會為那一部分的正規表示式設定或是移除對應的旗標。

  - `re.A`（僅限 ASCII 字元匹配）

  - `re.I`（忽略大小寫）

  - `re.L`（依賴區域設定）

  - `re.M`（多行）

  - `re.S`（點會匹配所有字元）

  - `re.U`（匹配 Unicode）

  - `re.X`（詳盡模式）

  （這些旗標在 Module contents 中說明。）

  字母 `'a'`、`'L'` 和 `'u'` 在被當作嵌入旗標時是互斥的，所以它們不能被組合使用或是接在 `'-'` 後面。相反地，當它們其中一個出現在嵌入群組時，它會覆蓋括號中群組的匹配模式。在 Unicode 模式中，`(?a:...)` 會切換到僅匹配 ASCII 模式，且 `(?u:...)` 會切換到 Unicode 匹配模式（預設）。在位元組模式，`(?L:...)` 會切換到依賴區域設定 (locale) 的匹配，且 `(?a:...)` 會切換到僅匹配 ASCII 模式（預設）。這個覆蓋只會在嵌入群組中作用，而原本的匹配模式會在群組外恢復。

  在 3.6 版被加入.

  在 3.7 版的變更: 字母 `'a'`、`'L'` 和 `'u'` 也可以被用在群組中。

`(?>...)`

  嘗試將 `...` 視為獨立的正規表示式進行匹配，且若成功則會繼續匹配後續的模式。如果後續模式匹配失敗，則回溯堆疊 (stack) 只能還原 (unwound) 到 `(?>...)` 之前，因為一旦退出了，這個也叫做原子群組 (atomic group) 的正規表示式，已經丟棄了它自己的所有回溯點 (stack point)。因此，`(?>.*).` 永遠不會匹配任何內容，因為 `.*` 會先盡可能匹配所有的字元，接著沒有任何剩餘內容可以匹配，導致最終的 `.` 匹配失敗。因為原子群組中沒有儲存回溯點，而且群組之前也沒有回溯點，整個正規表示式都會匹配失敗。

  在 3.11 版被加入.

`(?P<name>...)`

  類似於一般的括號，但是這個群組匹配的子字串可以透過符號群組名稱 name 存取。群組名稱必須是有效的 Python 識別字 (identifier)，並且在 `bytes` 模式中，它們只能包含 ASCII 範圍中的位元組。每個群組名稱在正規表示式中只能定義一次。一個符號群組同時也是一個編號群組，只是等同於該群組沒有名稱。

  命名群組 (named groups) 可以在三種情境下被參照。如果該模式是 `(?P<quote>['"]).*?(?P=quote)`（也就是匹配一個用單引號或雙引號包圍的字串）：

  對 "quote" 群組參照的情境 | 參照方式
  --- | ---

  在同一個模式中

  - `(?P=quote)`（如上例所示）

  - `\1`

  在處理匹配物件 m 時

  - `m.group('quote')`

  - `m.end('quote')`（等）

  在被當成 `re.sub()` 的 repl 引數傳入的字串中

  - `\g<quote>`

  - `\g<1>`

  - `\1`

  在 3.12 版的變更: 在 `bytes` 模式中，群組的名稱只能包含 ASCII 範圍中的位元組（`b'\x00'`-`b'\x7f'`）。

`(?P=name)`

  對於命名群組的反向參照；它會匹配任何之前被命名為 name 的群組所匹配到的文字。

`(?#...)`

  一個註解；括號中的內容會被忽略。

`(?=...)`

  如果字串接下來可以匹配 `...` 才會成功匹配，但是並不會消耗任何字串。這被稱作 lookahead assertion。例如，`Isaac (?=Asimov)` 只在後面跟著 `'Asimov'` 時才會匹配 `'Isaac '`。

`(?!...)`

  如果字串接下來不匹配 `...`，才會成功匹配。這是一個負向預查斷言 (negative lookahead assertion) <negative lookahead assertion>。例如，`Isaac (?!Asimov)` 只在後面不跟著 `'Asimov'` 時才會匹配 `'Isaac '`。

`(?<=...)`

  如果目前位置前方的字串能夠匹配 `...`，可以成功匹配。這叫做正向回查斷言 (positive lookbehind assertion) <positive lookbehind assertion>。`(?<=abc)def` 會在 `'abcdef'` 中找到一個匹配，因為回查會向後 3 個字元，並檢查是否能匹配包含的模式。這個包含的模式只能匹配固定長度的字串，代表 `abc` 或 `a|b` 是被允許的，但是 `a*` 和 `a{3,4}` 不被允許。請注意，使用正向回查斷言開頭的模式不會匹配被搜尋字串的開頭；你更可能想要使用 `search()` 函式而不是 `match()` 函式：

      >>> import re
      >>> m = re.search('(?<=abc)def', 'abcdef')
      >>> m.group(0)
      'def'

  這個範例在尋找連字號後的單字：

      >>> m = re.search(r'(?<=-)\w+', 'spam-egg')
      >>> m.group(0)
      'egg'

  在 3.5 版的變更: 新增固定長度群組參照的支援。

`(?<!...)`

  如果目前位置前方的字串不能夠匹配 `...`，可以成功匹配。這叫做負向回查斷言 (negative lookbehind assertion) <negative lookbehind assertion>。類似於正向回查斷言，包含的模式只能匹配固定長度的字串。使用負向回查斷言開頭的模式可以匹配被搜尋字串的開頭。

`(?(id/name)yes-pattern|no-pattern)`

  如果給定 id 或 name 的群組存在，會嘗試匹配 `yes-pattern`，否則會匹配 `no-pattern`。`no-pattern` 是可選的並且可以省略。例如，`(<)?(\w+@\w+(?:\.\w+)+)(?(1)>|$)` 是一個不好的電子郵件匹配模式，它會匹配 `'<user@host.com>'` 和 `'user@host.com'`，但不會匹配 `'<user@host.com'` 以及 `'user@host.com>'`。

  在 3.12 版的變更: 群組 id 只能包含 ASCII 數字。在 `bytes` 模式中，群組 name 只能包含 ASCII 範圍中的位元組 (`b'\x00'`-`b'\x7f'`)。

特殊序列由 `'\'` 和下列清單的一個字元組成。如果序列中的一般字元不是一個 ASCII 數字或是一個 ASCII 字母，那麼產生的的正規表示式會匹配第二個字元。例如，`\$` 會匹配字元 `'$'`。

`\number`

  匹配相同數字群組中的內容。群組會從 1 開始編號。例如，`(.+) \1` 會匹配 `'the the'` 或 `'55 55'`，但不會匹配 `'thethe'`（注意群組後的空格）。這個特殊序列只能用來匹配前 99 個群組之一。如果 number 的第一位數是 0，或是 number 有 3 個八進位位數，它就不會被解讀成匹配群組，而是解讀成八進位數值 number 的字元。在一個字元類別中的 `'['` 和 `']'`，所有數值的跳脫字元都會被當作字元。

`\A`

  只在字串的開頭匹配。

`\b`

  匹配空字串，但是只在一個單字的開頭或結尾。一個單字被定義為一個單字字元的序列。請注意在正式情況下，`\b` 被定義為 `\w` 和一個 `\W` 字元的邊界（或是反之亦然），或是在 `\w` 和字串的開頭或結尾之間。這表示 `r'\bat\b'` 會匹配 `'at'`、`'at.'`、`'(at)'`，以及 `'as at ay'`，但是不匹配 `'attempt'` 或 `'atlas'`。

  預設的單字字元在 Unicode（字串）模式中，是 Unicode 字母數字 (alphanumerics) 和底線，但是這可以透過使用 `ASCII` 旗標來改變。如果使用了 `LOCALE` 旗標，單字的邊界會由目前的區域設定決定。

  備註

  在字元範圍中，為了與 Python 的字串文本的相容性，`\b` 表示 backspace 字元。

`\B`

  匹配空字串，但是只有在空字串不在單字的開頭或結尾時匹配。這表示 `r'at\B'` 會匹配 `'athens'`、`'atom'`、`'attorney'`，但是不匹配 `'at'`、`'at.'` 或 `'at!'`。`\B` 是 `\b` 的相反，所以 Unicode（字串）模式中的單字字元是 Unicode 字母、數字或底線，不過這可以透過使用 `ASCII` 旗標來改變。如果使用了 `LOCALE` 旗標，單字的邊界會由目前的區域設定決定。

  在 3.14 版的變更: `\B` 現在會匹配空的輸入字串。

`\d`
  對於 Unicode（字串）模式：

    匹配任何 Unicode 十進位數字（也就是 Unicode 字元類別中的任何字元 [Nd]）。這包含了 `[0-9]`，以及許多許多其他的數字字元。

    如果使用了 `ASCII` 旗標，匹配 `[0-9]`。

  對於 8 位元（位元組）模式：

    匹配任何 ASCII 字元集合中的十進位數字；這等同於 `[0-9]`。

`\D`

  匹配任何不是十進位數字的字元。這是 `\d` 的相反。

  如果使用了 `ASCII` 旗標，會匹配 `[^0-9]`。

`\s`
  對於 Unicode（字串）模式：

    匹配 Unicode 空格字元（在 `str.isspace()` 中定義）。包含 `[ \t\n\r\f\v]`，還有許多其他的字元，例如許多語言的排版規則中要求的不換行空格。

    如果使用了 `ASCII` 旗標，匹配 `[ \t\n\r\f\v]`。

  對於 8 位元（位元組）模式：

    匹配 ASCII 字元集合中認定的空格；這等同於 `[ \t\n\r\f\v]`。

`\S`

  匹配任何不是空格字元的字元。這是 `\s` 的相反。

  如果使用了 `ASCII` 旗標，匹配 `[^ \t\n\r\f\v]`。

`\w`
  對於 Unicode（字串）模式：

    匹配 Unicode 單字字元；這包含全部 Unicode 的字母數字字元（在 `str.isalnum()` 中定義），以及底線 (`_`)。

    如果使用了 `ASCII` 旗標，匹配 `[a-zA-Z0-9_]`。

  對於 8 位元（位元組）模式：

    匹配在 ASCII 字元集合中被認定為字母或數字的字元；這等同於 `[a-zA-Z0-9_]`。如果使用了 `LOCALE` 旗標，會匹配目前區域設定中被認定為字母或數字的字元，以及底線。

`\W`

  匹配任何不是單字字元的字元。這是 `\w` 的相反。預設情況下，會匹配任何不是底線 (`_`)，並且 `str.isalnum()` 會回傳 `False` 的字元。

  如果使用了 `ASCII` 旗標，會匹配 `[^a-zA-Z0-9_]`。

  如果使用了 `LOCALE` 旗標，會匹配目前區域中不是字母數字，也不是底線的字元。

`\z`

  只在字串的結尾匹配。

  在 3.14 版被加入.

`\Z`

  和 `\z` 相同。為了與舊版的 Python 相容而保留。

大多數 Python 的字串文本支援的跳脫序列也能被正規表示式剖析器接受：

    \a      \b      \f      \n
    \N      \r      \t      \u
    \U      \v      \x      \\

（請注意 `\b` 被用來表示單字邊界，並且只在字元類別內表示 "backspace"。）

`'\u'`、`'\U'`，和 `'\N'` 跳脫序列只會在 Unicode（字串）模式中可辨認。在位元組模式中，它們是錯誤。未知的跳脫 ASCII 字母被保留於未來使用，並且會被當成錯誤。

八進位數的跳脫被有限地包含在內。如果第一個數字是一個 0，或是如果有三個八進位數字，它就會被當作是一個八進位跳脫。否則，它是一個群組參照。至於字串文本，八進位跳脫最多只能包含三個數字。

在 3.3 版的變更: `'\u'` 和 `'\U'` 跳脫序列已經被添加。

在 3.6 版的變更: 由 `'\'` 和一個 ASCII 字母組成的未知跳脫現在會是錯誤。

在 3.8 版的變更: `'\N{name}'` 跳脫序列已經被添加。如同字串文本，它會展開成命名的 Unicode 字元（如 `'\N{EM DASH}'`）。

## Module contents

The module defines several functions, constants, and an exception. Some of the functions are simplified versions of the full featured methods for compiled regular expressions. Most non-trivial applications always use the compiled form.

### 旗標

在 3.6 版的變更: Flag 常數現在是 `RegexFlag` 的實例，其為 `enum.IntFlag` 的子類別。

class re.RegexFlag

  包含下列正規表示式選項的一個 `enum.IntFlag` 類別。

  在 3.11 版被加入: - added to `__all__`

re.A
re.ASCII

  使 `\w`、`\W`、`\b`、`\B`、`\d`、`\D`、`\s` 和 `\S` 執行僅限 ASCII 的匹配，而不是完整的 Unicode 匹配。這只對 Unicode（字串）模式有意義，並且在位元組模式中會被忽略。

  對應到內嵌旗標 `(?a)`。

  備註

  為了向後相容，`U` 旗標仍然存在，但是在 Python 3 中是多餘的，因為對於 `str` 模式，匹配預設是 Unicode，並且不允許位元組模式進行 Unicode 匹配。`UNICODE` 和內嵌旗標 `(?u)` 也是類似的冗餘。

re.DEBUG

  顯示關於已編譯表示式的偵錯資訊。

  沒有對應的內嵌旗標。

re.I
re.IGNORECASE

  執行不區分大小寫的匹配；像是 `[A-Z]` 這樣的表示式也會匹配小寫字母。完整的 Unicode 匹配（例如 `Ü` 匹配 `ü`）也能正常運作，除非使用了 `ASCII` 旗標來停用非 ASCII 的匹配。除非也使用了 `LOCALE` 旗標，否則目前的區域設定不會改變這個旗標的效果。

  對應到內嵌旗標 `(?i)`。

  請注意，當 Unicode 模式 `[a-z]` 或 `[A-Z]` 與 `IGNORECASE` 旗標結合使用時，它們會匹配 52 個 ASCII 字母和另外 4 個非 ASCII 字母：'İ' (U+0130，帶點的大寫拉丁字母 I)、'ı' （U+0131，無點的小寫拉丁字母 i）、'ſ' （U+017F，拉丁小寫長 s）和 'K' （U+212A，開爾文符號）。如果使用了 `ASCII` 旗標，則只會匹配字母 'a' 到 'z' 和 'A' 到 'Z'。

re.L
re.LOCALE

  使 `\w`、`\W`、`\b`、`\B` 和不區分大小寫的匹配依賴於目前的區域設定。這個旗標只能用在位元組模式中。

  對應到內嵌旗標 `(?L)`。

  警告

  不建議使用這個旗標；請考慮使用 Unicode 匹配。區域設定機制非常不可靠，因為它一次只處理一種「文化」，並且只適用於 8 位元的區域設定。Unicode 匹配在 Unicode（字串）模式中預設是啟用的，並且能夠處理不同的區域設定和語言。

  在 3.6 版的變更: `LOCALE` 只能用在位元組模式中，並且與 `ASCII` 不相容。

  在 3.7 版的變更: 使用 `LOCALE` 旗標的已編譯正規表示式物件不再依賴於編譯時的區域設定。只有匹配時的區域設定會影響匹配的結果。

re.M
re.MULTILINE

  當指定時，模式字元 `'^'` 會在字串的開頭以及每一行的開頭（緊接在每個換行符號之後）匹配；而模式字元 `'$'` 會在字串的結尾以及每一行的結尾（緊接在每個換行符號之前）匹配。預設情況下，`'^'` 只會在字串的開頭匹配，而 `'$'` 只會在字串的結尾以及字串結尾（如果有的話）緊接在換行符號之前匹配。

  對應到內嵌旗標 `(?m)`。

re.NOFLAG

  表示沒有應用任何旗標，值為 `0`。這個旗標可以用作函式關鍵字引數的預設值，或是作為一個基底值，將會有條件地與其他旗標進行 OR 運算。作為預設值使用的範例：

      def myfunc(pattern, text, flag=re.NOFLAG):
          return re.search(pattern, text, flag)

  在 3.11 版被加入.

re.S
re.DOTALL

  使 `'.'` 特殊字元能夠匹配任何字元，包括換行符號；如果沒有這個旗標，`'.'` 只會匹配除了換行符號以外的任何字元。

  對應到內嵌旗標 `(?s)`。

re.U
re.UNICODE

  在 Python 3 中，Unicode 字元在 `str` 模式中預設會被匹配。因此這個旗標是多餘的，沒有任何效果，並且僅為了向後相容而保留。

  請參閱 `ASCII` 以將匹配限制為 ASCII 字元。

re.X
re.VERBOSE

  這個旗標透過讓你在視覺上分隔模式的邏輯區塊並添加註解，使你能夠撰寫看起來更好且更易讀的正規表示式。模式中的空白會被忽略，除非在字元類別中，或是前面有一個未跳脫的反斜線，或是在像是 `*?`、`(?:` 或 `(?P<...>` 這樣的標記中。例如，`(? :` 和 `* ?` 是不允許的。當一行包含一個不在字元類別中且前面沒有未跳脫反斜線的 `#` 時，從最左邊的這個 `#` 到行尾的所有字元都會被忽略。

  這表示下面兩個匹配十進位數字的正規表示式物件在功能上是相等的：

      a = re.compile(r"""\d +  # 整數部分
                         \.    # 小數點
                         \d *  # 一些小數位""", re.X)
      b = re.compile(r"\d+\.\d*")

  對應到內嵌旗標 `(?x)`。

### 函式

re.compile(pattern, flags=0)

  Compile a regular expression pattern into a regular expression object, which can be used for matching using its `prefixmatch()`, `search()`, and other methods, described below.

  可以透過指定 flags 值來修改正規表示式的行為，值可以是任何 flags 變數，使用位元 OR（bitwise OR、`|` 運算子）組合。

  序列為：

      prog = re.compile(pattern)
      result = prog.search(string)

  等價於：

      result = re.search(pattern, string)

  但是當表示式在單一程式中多次使用時，使用 `re.compile()` 並保存產生的正規表示式物件以供重複使用會更有效率。

  備註

  傳遞給 `re.compile()` 之最新模式的編譯版本和模組層級匹配函式都會被快取，因此一次僅使用幾個正規表示式的程式不必去擔心編譯正規表示式。

re.search(pattern, string, flags=0)

  掃描 string 以尋找正規表示式 pattern 產生匹配的第一個位置，並回傳對應的 `Match`。如果字串中沒有與模式匹配的位置則回傳 `None`；請注意，這與在字串中的某個點查找零長度匹配不同。

  可以透過指定 flags 值來修改正規表示式的行為，值可以是任何 flags 變數，使用位元 OR（bitwise OR、`|` 運算子）組合。

re.prefixmatch(pattern, string, flags=0)

  如果 string 開頭的零個或多個字元與正規表示式 pattern 匹配，則回傳對應的 `Match`。如果字串與模式不匹配，則回傳 `None`；請注意，這與零長度匹配不同。

  備註

  Even in `MULTILINE` mode, this will only match at the beginning of the string and not at the beginning of each line.

  如果你想在 string 中的任何位置找到匹配項，請使用 `search()`（另請參閱 search() vs. prefixmatch()）。

  可以透過指定 flags 值來修改正規表示式的行為，值可以是任何 flags 變數，使用位元 OR（bitwise OR、`|` 運算子）組合。

  This function now has two names and has long been known as `match()`. Use that name when you need to retain compatibility with older Python versions.

  在 3.15 版被加入.

re.match(pattern, string, flags=0)

  Soft deprecated since version 3.15: `match()` has been soft deprecated in favor of the alternate `prefixmatch()` name of this API which is more explicitly descriptive. Use it to better express intent. The norm in other languages and regular expression implementations is to use the term match to refer to the behavior of what Python has always called `search()`. See prefixmatch() vs. match().

re.fullmatch(pattern, string, flags=0)

  如果整個 string 與正規表示式 pattern 匹配，則回傳對應的 `Match`。如果字串與模式不匹配，則回傳 `None`；請注意，這與零長度匹配不同。

  可以透過指定 flags 值來修改正規表示式的行為，值可以是任何 flags 變數，使用位元 OR（bitwise OR、`|` 運算子）組合。

  在 3.4 版被加入.

re.split(pattern, string, maxsplit=0, flags=0)

  依 pattern 的出現次數拆分 string。如果在 pattern 中使用捕獲括號，則模式中所有群組的文字也會作為結果串列的一部分回傳。如果 maxsplit 非零，則最多發生 maxsplit 次拆分，並且字串的其餘部分會作為串列的最終元素回傳。

      >>> re.split(r'\W+', 'Words, words, words.')
      ['Words', 'words', 'words', '']
      >>> re.split(r'(\W+)', 'Words, words, words.')
      ['Words', ', ', 'words', ', ', 'words', '.', '']
      >>> re.split(r'\W+', 'Words, words, words.', maxsplit=1)
      ['Words', 'words, words.']
      >>> re.split('[a-f]+', '0a3B9', flags=re.IGNORECASE)
      ['0', '3', '9']

  如果分隔符號中有捕獲群組並且它在字串的開頭匹配，則結果將以空字串開頭。這同樣適用於字串的結尾：

      >>> re.split(r'(\W+)', '...words, words...')
      ['', '...', 'words', ', ', 'words', '...', '']

  如此一來，分隔符號元件始終可以在結果串列中的相同相對索引處找到。

  Adjacent empty matches are not possible, but an empty match can occur immediately after a non-empty match.

      >>> re.split(r'\b', 'Words, words, words.')
      ['', 'Words', ', ', 'words', ', ', 'words', '.']
      >>> re.split(r'\W*', '...words...')
      ['', '', 'w', 'o', 'r', 'd', 's', '', '']
      >>> re.split(r'(\W*)', '...words...')
      ['', '...', '', '', 'w', '', 'o', '', 'r', '', 'd', '', 's', '...', '', '', '']

  可以透過指定 flags 值來修改正規表示式的行為，值可以是任何 flags 變數，使用位元 OR（bitwise OR、`|` 運算子）組合。

  在 3.1 版的變更: 新增可選旗標引數。

  在 3.7 版的變更: 新增了對可以匹配空字串之模式進行拆分的支援。

  在 3.13 版之後被棄用: 將 maxsplit 和 flags 作為位置引數傳遞的用法已被棄用。在未來的 Python 版本中，它們將會是僅限關鍵字參數。

re.findall(pattern, string, flags=0)

  以字串或元組串列的形式回傳 string 中 pattern 的所有非重疊匹配項。從左到右掃描 string，並按找到的順序回傳符合項目。結果中會包含空匹配項。

  結果取決於模式中捕獲群組的數量。如果沒有群組，則回傳與整個模式匹配的字串串列。如果恰好存在一個群組，則回傳與該群組匹配的字串串列。如果存在多個群組，則回傳與群組匹配的字串元組串列。非捕獲群組則不影響結果的形式。

      >>> re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest')
      ['foot', 'fell', 'fastest']
      >>> re.findall(r'(\w+)=(\d+)', 'set width=20 and height=10')
      [('width', '20'), ('height', '10')]

  可以透過指定 flags 值來修改正規表示式的行為，值可以是任何 flags 變數，使用位元 OR（bitwise OR、`|` 運算子）組合。

  在 3.7 版的變更: 非空匹配現在可以剛好在前一個空匹配的後面開始。

re.finditer(pattern, string, flags=0)

  回傳一個 iterator，在 string 中的 RE pattern 的所有非重疊匹配上 yield `Match` 物件。從左到右掃描 string，並按找到的順序回傳匹配項目。結果中包含空匹配項。

  可以透過指定 flags 值來修改正規表示式的行為，值可以是任何 flags 變數，使用位元 OR（bitwise OR、`|` 運算子）組合。

  在 3.7 版的變更: 非空匹配現在可以剛好在前一個空匹配的後面開始。

re.sub(pattern, repl, string, count=0, flags=0)

  回傳透過以替換 repl 取代 string 中最左邊不重疊出現的 pattern 所獲得的字串。如果未找到該模式，則不改變 string 並回傳。repl 可以是字串或函式；如果它是字串，則處理其中的任何反斜線跳脫。也就是說 `\n` 會被轉換為單一換行符、`\r` 會被轉換為回車符 (carriage return) 等等。ASCII 字母的未知跳脫符會被保留以供將來使用並被視為錯誤。其他未知跳脫符例如 `\&` 會被單獨保留。例如 `\6` 的反向參照將被替換為模式中第 6 組匹配的子字串。例如：

      >>> re.sub(r'def\s+([a-zA-Z_][a-zA-Z_0-9]*)\s*\(\s*\):',
      ...        r'static PyObject*\npy_\1(void)\n{',
      ...        'def myfunc():')
      'static PyObject*\npy_myfunc(void)\n{'

  如果 repl 是一個函式，則 pattern 的每個不重疊出現之處都會呼叫它。此函式接收單一 `Match` 引數，並回傳替換字串。例如：

      >>> def dashrepl(matchobj):
      ...     if matchobj.group(0) == '-': return ' '
      ...     else: return '-'
      ...
      >>> re.sub('-{1,2}', dashrepl, 'pro----gram-files')
      'pro--gram files'
      >>> re.sub(r'\sAND\s', ' & ', 'Baked Beans And Spam', flags=re.IGNORECASE)
      'Baked Beans & Spam'

  此模式可以是字串或 `Pattern`。

  可選引數 count 是要替換的模式出現的最大次數；count 必須是非負整數。如果省略或為零，則所有出現的內容都將被替換。

  Adjacent empty matches are not possible, but an empty match can occur immediately after a non-empty match. As a result, `sub('x*', '-', 'abxd')` returns `'-a-b--d-'` instead of `'-a-b-d-'`.

  在字串型別 repl 引數中，除了上述字元跳脫和反向參照之外，`\g<name>` 將使用名為 `name` 的群組所匹配到的子字串，如 `(?P<name>...)` 所定義的語法。`\g<number>` 使用對應的群組編號；因此 `\g<2>` 等價於 `\2`，但在諸如 `\g<2>0` 之類的替換中並非模糊不清 (isn't ambiguous)。`\20` 將被直譯為對群組 20 的參照，而不是對後面跟著字面字元 `'0'` 的群組 2 的參照。反向參照 `\g<0>` 會取代以 RE 所匹配到的整個子字串。

  可以透過指定 flags 值來修改正規表示式的行為，值可以是任何 flags 變數，使用位元 OR（bitwise OR、`|` 運算子）組合。

  在 3.1 版的變更: 新增可選旗標引數。

  在 3.5 版的變更: 不匹配的群組將被替換為空字串。

  在 3.6 版的變更: 在由 `'\'` 和一個 ASCII 字母組成之 pattern 中的未知跳脫符現在為錯誤。

  在 3.7 版的變更: 由 `'\'` 和一個 ASCII 字母組成之 repl 中的未知跳脫符現在為錯誤。非空匹配後可以緊接著出現空匹配。

  在 3.12 版的變更: 群組 id 只能包含 ASCII 數字。在 `bytes` 替換字串中，群組 name 只能包含 ASCII 範圍內的位元組 (`b'\x00'`-`b'\x7f'`)。

  在 3.13 版之後被棄用: 將 count 和 flags 作為位置引數傳遞的用法已被棄用。在未來的 Python 版本中，它們將會是僅限關鍵字參數。

re.subn(pattern, repl, string, count=0, flags=0)

  執行與 `sub()` 相同的操作，但回傳一個元組 `(new_string, number_of_subs_made)`。

  可以透過指定 flags 值來修改正規表示式的行為，值可以是任何 flags 變數，使用位元 OR（bitwise OR、`|` 運算子）組合。

re.escape(pattern)

  對 pattern 中的特殊字元進行跳脫。如果你想要匹配其中可能包含正規表示式元字元 (metacharacter) 的任何文本字串，這會非常有用。例如：

      >>> print(re.escape('https://www.python.org'))
      https://www\.python\.org

      >>> legal_chars = string.ascii_lowercase + string.digits + "!#$%&'*+-.^_`|~:"
      >>> print('[%s]+' % re.escape(legal_chars))
      [abcdefghijklmnopqrstuvwxyz0123456789!\#\$%\&'\*\+\-\.\^_`\|\~:]+

      >>> operators = ['+', '-', '*', '/', '**']
      >>> print('|'.join(map(re.escape, sorted(operators, reverse=True))))
      /|\-|\+|\*\*|\*

  此函式不得用於 `sub()` 和 `subn()` 中的替換字串，僅應跳脫反斜線。例如：

      >>> digits_re = r'\d+'
      >>> sample = '/usr/sbin/sendmail - 0 errors, 12 warnings'
      >>> print(re.sub(digits_re, digits_re.replace('\\', r'\\'), sample))
      /usr/sbin/sendmail - \d+ errors, \d+ warnings

  在 3.3 版的變更: `'_'` 字元不再被跳脫。

  在 3.7 版的變更: Only characters that can have special meaning in a regular expression are escaped. As a result, `'!'`, `'"'`, `'%'`, `"'"`, `','`, `'/'`, `':'`, `';'`, `'<'`, `'='`, `'>'`, `'@'`, and `"`"` are no longer escaped.

re.purge()

  清除正規表示式快取。

### 例外

exception re.PatternError(msg, pattern=None, pos=None)

  當傳遞給此處函式之一的字串不是有效的正規表示式（例如它可能包含不匹配的括號）或在編譯或匹配期間發生某些其他錯誤時，將引發例外。如果字串不包含模式匹配項，則絕不是錯誤。`PatternError` 實例具有以下附加屬性：

  msg

    未格式化的錯誤訊息。

  pattern

    正規表示式模式。

  pos

    pattern 中編譯失敗的索引（可能是 `None`）。

  lineno

    對應 pos 的列（可能是 `None`）。

  colno

    對應 pos 的欄（可能是 `None`）。

  在 3.5 版的變更: 新增額外屬性。

  在 3.13 版的變更: `PatternError` 最初被命名為 `error`；後者為了向後相容性而被保留為別名。

## Regular expression objects

class re.Pattern

  由 `re.compile()` 回傳的已編譯正規表示式物件。

  在 3.9 版的變更: `re.Pattern` 支援 `[]` 以表示 Unicode（字串）或位元組模式。請參閱 泛型別名型別。

Pattern.search(string[, pos[, endpos]])

  掃描 string 以尋找此正規表示式產生匹配的第一個位置，並回傳對應的 `Match`。如果字串中沒有與模式匹配的位置則回傳 `None`；請注意，這與在字串中的某個點查找零長度匹配不同。

  可選的第二個參數 pos 提供字串中的索引，表示要從哪裡開始搜尋；預設值為 `0`。這並不完全等同於對字串進行切片；`'^'` 模式字元會在字串的實際開頭和換行之後的位置匹配，但不一定是在要開始搜尋的索引處。

  可選的參數 endpos 限制了字串將被搜尋的範圍；就好像字串的長度為 endpos 個字元一樣，因此只有從 pos 到 `endpos - 1` 的字元會被搜尋以尋找匹配項。如果 endpos 小於 pos，則不會找到匹配項；否則，如果 rx 是已編譯的正規表示式物件，則 `rx.search(string, 0, 50)` 等價於 `rx.search(string[:50], 0)`。

      >>> pattern = re.compile("d")
      >>> pattern.search("dog")     # 在索引 0 處匹配
      <re.Match object; span=(0, 1), match='d'>
      >>> pattern.search("dog", 1)  # 無匹配；搜尋不包含 "d"

Pattern.prefixmatch(string[, pos[, endpos]])

  如果在 string 的開頭處有零個或多個字元與此正規表示式匹配，則回傳對應的 `Match`。如果字串與模式不匹配，則回傳 `None`；請注意，這與零長度匹配不同。

  Note that even in `MULTILINE` mode, this will only match at the beginning of the string and not at the beginning of each line.

  可選的 pos 和 endpos 參數與 `search()` 方法中的參數具有相同的意義。

      >>> pattern = re.compile("o")
      >>> pattern.prefixmatch("dog")     # No match as "o" is not at the start of "dog".
      >>> pattern.prefixmatch("dog", 1)  # Match as "o" is the 2nd character of "dog".
      <re.Match object; span=(1, 2), match='o'>

  如果你想在 string 中的任何位置找到匹配，請改用 `search()`（另請參閱 search() vs. prefixmatch()）。

  This method now has two names and has long been known as `match()`. Use that name when you need to retain compatibility with older Python versions.

  在 3.15 版被加入.

Pattern.match(string[, pos[, endpos]])

  Soft deprecated since version 3.15: `match()` has been soft deprecated in favor of the alternate `prefixmatch()` name of this API which is more explicitly descriptive. Use it to better express intent. The norm in other languages and regular expression implementations is to use the term match to refer to the behavior of what Python has always called `search()`. See prefixmatch() vs. match().

Pattern.fullmatch(string[, pos[, endpos]])

  如果整個 string 與此正規表示式匹配，則回傳對應的 `Match`。如果字串與模式不匹配，則回傳 `None`；請注意，這與零長度匹配不同。

  可選的 pos 和 endpos 參數與 `search()` 方法中的參數具有相同的意義。

      >>> pattern = re.compile("o[gh]")
      >>> pattern.fullmatch("dog")      # 無匹配，因為 "o" 不在 "dog" 的開頭。
      >>> pattern.fullmatch("ogre")     # 無匹配，因為整個字串不匹配。
      >>> pattern.fullmatch("doggie", 1, 3)   # 在給定限制內匹配。
      <re.Match object; span=(1, 3), match='og'>

  在 3.4 版被加入.

Pattern.split(string, maxsplit=0)

  和 `split()` 函式相同，使用已編譯的模式。

Pattern.findall(string[, pos[, endpos]])

  類似於 `findall()` 函式，使用已編譯的模式，但也接受可選的 pos 和 endpos 參數，這些參數會像 `search()` 一樣限制搜尋區域。

Pattern.finditer(string[, pos[, endpos]])

  類似於 `finditer()` 函式，使用已編譯的模式，但也接受可選的 pos 和 endpos 參數，這些參數會像 `search()` 一樣限制搜尋區域。

Pattern.sub(repl, string, count=0)

  和 `sub()` 函式相同，使用已編譯的模式。

Pattern.subn(repl, string, count=0)

  和 `subn()` 函式相同，使用已編譯的模式。

Pattern.flags

  正規表示式匹配旗標。這是傳遞給 `compile()` 的旗標、模式中的任何 `(?...)` 內嵌旗標以及隱含旗標（例如如果模式是 Unicode 字串則為 `UNICODE`）的組合。

Pattern.groups

  模式中捕獲群組的數量。

Pattern.groupindex

  一個字典，將任何由 `(?P<id>)` 定義的符號群組名稱對映到群組編號。如果模式中未使用符號群組，則字典為空。

Pattern.pattern

  從中編譯出模式物件的模式字串。

在 3.7 版的變更: 新增對 `copy.copy()` 和 `copy.deepcopy()` 的支援。已編譯的正規表示式物件被視為不可分割的 (atomic)。

## Match objects

Match objects always have a boolean value of `True`. Since `match()` and `search()` return `None` when there is no match, you can test whether there was a match with a simple `if` statement:

    if match := re.search(pattern, string):
        process(match)

class re.Match

  Match object returned by successful `match`es and `search`es.

  在 3.9 版的變更: `re.Match` supports `[]` to indicate a Unicode (str) or bytes match. See 泛型別名型別.

Match.expand(template)

  Return the string obtained by doing backslash substitution on the template string template, as done by the `sub()` method. Escapes such as `\n` are converted to the appropriate characters, and numeric backreferences (`\1`, `\2`) and named backreferences (`\g<1>`, `\g<name>`) are replaced by the contents of the corresponding group. The backreference `\g<0>` will be replaced by the entire match.

  在 3.5 版的變更: 不匹配的群組將被替換為空字串。

Match.group([group1, ...])

  Returns one or more subgroups of the match. If there is a single argument, the result is a single string; if there are multiple arguments, the result is a tuple with one item per argument. Without arguments, group1 defaults to zero (the whole match is returned). If a groupN argument is zero, the corresponding return value is the entire matching string; if it is a positive integer, it is the string matching the corresponding parenthesized group. If a group number is negative or larger than the number of groups defined in the pattern, an `IndexError` exception is raised. If a group is contained in a part of the pattern that did not match, the corresponding result is `None`. If a group is contained in a part of the pattern that matched multiple times, the last match is returned.

      >>> m = re.search(r"\A(\w+) (\w+)", "Norwegian Blue, pining for the fjords")
      >>> m.group(0)       # The entire match
      'Norwegian Blue'
      >>> m.group(1)       # The first parenthesized subgroup.
      'Norwegian'
      >>> m.group(2)       # The second parenthesized subgroup.
      'Blue'
      >>> m.group(1, 2)    # Multiple arguments give us a tuple.
      ('Norwegian', 'Blue')

  If the regular expression uses the `(?P<name>...)` syntax, the groupN arguments may also be strings identifying groups by their group name. If a string argument is not used as a group name in the pattern, an `IndexError` exception is raised.

  A moderately complicated example:

      >>> m = re.search(r"(?P<adjective>\w+) (?P<animal>\w+)", "killer rabbit")
      >>> m.group('adjective')
      'killer'
      >>> m.group('animal')
      'rabbit'

  Named groups can also be referred to by their index:

      >>> m.group(1)
      'killer'
      >>> m.group(2)
      'rabbit'

  If a group matches multiple times, only the last match is accessible:

      >>> m = re.search(r"(..)+", "a1b2c3")  # Matches 3 times.
      >>> m.group(1)                         # Returns only the last match.
      'c3'

Match.__getitem__(g)

  This is identical to `m.group(g)`. This allows easier access to an individual group from a match:

      >>> m = re.search(r"(\w+) (\w+)", "Norwegian Blue, pining for the fjords")
      >>> m[0]       # The entire match
      'Norwegian Blue'
      >>> m[1]       # The first parenthesized subgroup.
      'Norwegian'
      >>> m[2]       # The second parenthesized subgroup.
      'Blue'

  Named groups are supported as well:

      >>> m = re.search(r"(?P<adjective>\w+) (?P<animal>\w+)", "killer rabbit")
      >>> m['adjective']
      'killer'
      >>> m['animal']
      'rabbit'

  在 3.6 版被加入.

Match.groups(default=None)

  Return a tuple containing all the subgroups of the match, from 1 up to however many groups are in the pattern. The default argument is used for groups that did not participate in the match; it defaults to `None`.

  舉例來說：

      >>> m = re.search(r"(\d+)\.(\d+)", "24.1632")
      >>> m.groups()
      ('24', '1632')

  If we make the decimal place and everything after it optional, not all groups might participate in the match. These groups will default to `None` unless the default argument is given:

      >>> m = re.search(r"(\d+)\.?(\d+)?", "24")
      >>> m.groups()      # Second group defaults to None.
      ('24', None)
      >>> m.groups('0')   # Now, the second group defaults to '0'.
      ('24', '0')

Match.groupdict(default=None)

  Return a dictionary containing all the named subgroups of the match, keyed by the subgroup name. The default argument is used for groups that did not participate in the match; it defaults to `None`. For example:

      >>> m = re.search(r"(?P<adjective>\w+) (?P<animal>\w+)", "killer rabbit")
      >>> m.groupdict()
      {'adjective': 'killer', 'animal': 'rabbit'}

Match.start([group])
Match.end([group])

  Return the indices of the start and end of the substring matched by group; group defaults to zero (meaning the whole matched substring). Return `-1` if group exists but did not contribute to the match. For a match object m, and a group g that did contribute to the match, the substring matched by group g (equivalent to `m.group(g)`) is

      m.string[m.start(g):m.end(g)]

  Note that `m.start(group)` will equal `m.end(group)` if group matched a null string. For example, after `m = re.search('b(c?)', 'cba')`, `m.start(0)` is 1, `m.end(0)` is 2, `m.start(1)` and `m.end(1)` are both 2, and `m.start(2)` raises an `IndexError` exception.

  An example that will remove remove_this from email addresses:

      >>> email = "tony@tiremove_thisger.net"
      >>> m = re.search("remove_this", email)
      >>> email[:m.start()] + email[m.end():]
      'tony@tiger.net'

Match.span([group])

  For a match m, return the 2-tuple `(m.start(group), m.end(group))`. Note that if group did not contribute to the match, this is `(-1, -1)`. group defaults to zero, the entire match.

Match.pos

  The value of pos which was passed to the `search()` or `match()` method of a regex object. This is the index into the string at which the RE engine started looking for a match.

Match.endpos

  The value of endpos which was passed to the `search()` or `match()` method of a regex object. This is the index into the string beyond which the RE engine will not go.

Match.lastindex

  The integer index of the last matched capturing group, or `None` if no group was matched at all. For example, the expressions `(a)b`, `((a)(b))`, and `((ab))` will have `lastindex == 1` if applied to the string `'ab'`, while the expression `(a)(b)` will have `lastindex == 2`, if applied to the same string.

Match.lastgroup

  The name of the last matched capturing group, or `None` if the group didn't have a name, or if no group was matched at all.

Match.re

  The regular expression object whose `match()` or `search()` method produced this match instance.

Match.string

  The string passed to `match()` or `search()`.

在 3.7 版的變更: Added support of `copy.copy()` and `copy.deepcopy()`. Match objects are considered atomic.

## Regular expression examples

### Checking for a pair

In this example, we'll use the following helper function to display match objects a little more gracefully:

    def displaymatch(match):
        if match is None:
            return None
        return '<Match: %r, groups=%r>' % (match.group(), match.groups())

Suppose you are writing a poker program where a player's hand is represented as a 5-character string with each character representing a card, "a" for ace, "k" for king, "q" for queen, "j" for jack, "t" for 10, and "2" through "9" representing the card with that value.

To see if a given string is a valid hand, one could do the following:

    >>> valid_hand_re = re.compile(r"^[a2-9tjqk]{5}$")
    >>> displaymatch(valid_hand_re.search("akt5q"))  # Valid.
    "<Match: 'akt5q', groups=()>"
    >>> displaymatch(valid_hand_re.search("akt5e"))  # Invalid.
    >>> displaymatch(valid_hand_re.search("akt"))    # Invalid.
    >>> displaymatch(valid_hand_re.search("727ak"))  # Valid.
    "<Match: '727ak', groups=()>"

That last hand, `"727ak"`, contained a pair, or two of the same valued cards. To match this with a regular expression, one could use backreferences as such:

    >>> pair_re = re.compile(r".*(.).*\1")
    >>> displaymatch(pair_re.prefixmatch("717ak"))     # Pair of 7s.
    "<Match: '717', groups=('7',)>"
    >>> displaymatch(pair_re.prefixmatch("718ak"))     # No pairs.
    >>> displaymatch(pair_re.prefixmatch("354aa"))     # Pair of aces.
    "<Match: '354aa', groups=('a',)>"

To find out what card the pair consists of, one could use the `group()` method of the match object in the following manner:

    >>> pair_re = re.compile(r".*(.).*\1")
    >>> pair_re.prefixmatch("717ak").group(1)
    '7'

    # Error because prefixmatch() returns None, which doesn't have a group() method:
    >>> pair_re.prefixmatch("718ak").group(1)
    Traceback (most recent call last):
      File "<pyshell#23>", line 1, in <module>
        pair_re.prefixmatch("718ak").group(1)
    AttributeError: 'NoneType' object has no attribute 'group'

    >>> pair_re.prefixmatch("354aa").group(1)
    'a'

### 模擬 scanf()

Python does not currently have an equivalent to `scanf()`. Regular expressions are generally more powerful, though also more verbose, than `scanf()` format strings. The table below offers some more-or-less equivalent mappings between `scanf()` format tokens and regular expressions.

`scanf()` Token | Regular Expression
--- | ---
`%c` | `.`
`%5c` | `.{5}`
`%d` | `[-+]?\d+`
`%e`, `%E`, `%f`, `%g` | `[-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?`
`%i` | `[-+]?(0[xX][\dA-Fa-f]+|0[0-7]*|\d+)`
`%o` | `[-+]?[0-7]+`
`%s` | `\S+`
`%u` | `\d+`
`%x`、`%X` | `[-+]?(0[xX])?[\dA-Fa-f]+`

To extract the filename and numbers from a string like:

    /usr/sbin/sendmail - 0 errors, 4 warnings

you would use a `scanf()` format like:

    %s - %d errors, %d warnings

The equivalent regular expression would be:

    (\S+) - (\d+) errors, (\d+) warnings

### search() vs. prefixmatch()

Python offers different primitive operations based on regular expressions:

- `re.prefixmatch()` checks for a match only at the beginning of the string

- `re.search()` checks for a match anywhere in the string (this is what Perl does by default)

- `re.fullmatch()` checks for entire string to be a match

舉例來說：

    >>> re.prefixmatch("c", "abcdef")  # No match
    >>> re.search("c", "abcdef")       # Match
    <re.Match object; span=(2, 3), match='c'>
    >>> re.fullmatch("p.*n", "python") # Match
    <re.Match object; span=(0, 6), match='python'>
    >>> re.fullmatch("r.*n", "python") # No match

Regular expressions beginning with `'^'` can be used with `search()` to restrict the match at the beginning of the string:

    >>> re.prefixmatch("c", "abcdef")  # No match
    >>> re.search("^c", "abcdef")      # No match
    >>> re.search("^a", "abcdef")      # Match
    <re.Match object; span=(0, 1), match='a'>

Note however that in `MULTILINE` mode `prefixmatch()` only matches at the beginning of the string, whereas using `search()` with a regular expression beginning with `'^'` will match at the beginning of each line.

    >>> re.prefixmatch("X", "A\nB\nX", re.MULTILINE)  # No match
    >>> re.search("^X", "A\nB\nX", re.MULTILINE)  # Match
    <re.Match object; span=(4, 5), match='X'>

### prefixmatch() vs. match()

Why is the `match()` function and method discouraged in favor of the longer `prefixmatch()` spelling?

Many other languages have gained regex support libraries since regular expressions were added to Python. However in the most popular of those, they use the term match in their APIs to mean the unanchored behavior provided in Python by `search()`. Thus use of the plain term match can be unclear to those used to other languages when reading or writing code and not familiar with the Python API's divergence from what otherwise become the industry norm.

Quoting from the Zen Of Python (`python3 -m this`): "Explicit is better than implicit". Anyone reading the name `prefixmatch()` is likely to understand the intended semantics. When reading `match()` there remains a seed of doubt about the intended behavior to anyone not already familiar with this old Python gotcha.

We do not plan to remove the older `match()` name, as it has been used in code for over 30 years. It has been soft deprecated: code supporting older versions of Python should continue to use `match()`, while new code should prefer `prefixmatch()`.

在 3.15 版被加入: `prefixmatch()`

Soft deprecated since version 3.15: `match()`

### Making a phonebook

`split()` splits a string into a list delimited by the passed pattern. The method is invaluable for converting textual data into data structures that can be easily read and modified by Python as demonstrated in the following example that creates a phonebook.

First, here is the input. Normally it may come from a file, here we are using triple-quoted string syntax

    >>> text = """Ross McFluff: 834.345.1254 155 Elm Street
    ...
    ... Ronald Heathmore: 892.345.3428 436 Finley Avenue
    ... Frank Burger: 925.541.7625 662 South Dogwood Way
    ...
    ...
    ... Heather Albrecht: 548.326.4584 919 Park Place"""

The entries are separated by one or more newlines. Now we convert the string into a list with each nonempty line having its own entry:

    >>> entries = re.split("\n+", text)
    >>> entries
    ['Ross McFluff: 834.345.1254 155 Elm Street',
    'Ronald Heathmore: 892.345.3428 436 Finley Avenue',
    'Frank Burger: 925.541.7625 662 South Dogwood Way',
    'Heather Albrecht: 548.326.4584 919 Park Place']

Finally, split each entry into a list with first name, last name, telephone number, and address. We use the `maxsplit` parameter of `split()` because the address has spaces, our splitting pattern, in it:

    >>> [re.split(":? ", entry, maxsplit=3) for entry in entries]
    [['Ross', 'McFluff', '834.345.1254', '155 Elm Street'],
    ['Ronald', 'Heathmore', '892.345.3428', '436 Finley Avenue'],
    ['Frank', 'Burger', '925.541.7625', '662 South Dogwood Way'],
    ['Heather', 'Albrecht', '548.326.4584', '919 Park Place']]

The `:?` pattern matches the colon after the last name, so that it does not occur in the result list. With a `maxsplit` of `4`, we could separate the house number from the street name:

    >>> [re.split(":? ", entry, maxsplit=4) for entry in entries]
    [['Ross', 'McFluff', '834.345.1254', '155', 'Elm Street'],
    ['Ronald', 'Heathmore', '892.345.3428', '436', 'Finley Avenue'],
    ['Frank', 'Burger', '925.541.7625', '662', 'South Dogwood Way'],
    ['Heather', 'Albrecht', '548.326.4584', '919', 'Park Place']]

### Text munging

`sub()` replaces every occurrence of a pattern with a string or the result of a function. This example demonstrates using `sub()` with a function to "munge" text, or randomize the order of all the characters in each word of a sentence except for the first and last characters:

    >>> def repl(m):
    ...     inner_word = list(m.group(2))
    ...     random.shuffle(inner_word)
    ...     return m.group(1) + "".join(inner_word) + m.group(3)
    ...
    >>> text = "Professor Abdolmalek, please report your absences promptly."
    >>> re.sub(r"(\w)(\w+)(\w)", repl, text)
    'Poefsrosr Aealmlobdk, pslaee reorpt your abnseces plmrptoy.'
    >>> re.sub(r"(\w)(\w+)(\w)", repl, text)
    'Pofsroser Aodlambelk, plasee reoprt yuor asnebces potlmrpy.'

### Finding all adverbs

`findall()` matches all occurrences of a pattern, not just the first one as `search()` does. For example, if a writer wanted to find all of the adverbs in some text, they might use `findall()` in the following manner:

    >>> text = "He was carefully disguised but captured quickly by police."
    >>> re.findall(r"\w+ly\b", text)
    ['carefully', 'quickly']

### Finding all adverbs and their positions

If one wants more information about all matches of a pattern than the matched text, `finditer()` is useful as it provides `Match` objects instead of strings. Continuing with the previous example, if a writer wanted to find all of the adverbs and their positions in some text, they would use `finditer()` in the following manner:

    >>> text = "He was carefully disguised but captured quickly by police."
    >>> for m in re.finditer(r"\w+ly\b", text):
    ...     print('%02d-%02d: %s' % (m.start(), m.end(), m.group(0)))
    07-16: carefully
    40-47: quickly

### Raw string notation

Raw string notation (`r"text"`) keeps regular expressions sane. Without it, every backslash (`'\'`) in a regular expression would have to be prefixed with another one to escape it. For example, the two following lines of code are functionally identical:

    >>> re.search(r"\W(.)\1\W", " ff ")
    <re.Match object; span=(0, 4), match=' ff '>
    >>> re.search("\\W(.)\\1\\W", " ff ")
    <re.Match object; span=(0, 4), match=' ff '>

When one wants to match a literal backslash, it must be escaped in the regular expression. With raw string notation, this means `r"\\"`. Without raw string notation, one must use `"\\\\"`, making the following lines of code functionally identical:

    >>> re.search(r"\\", r"\\")
    <re.Match object; span=(0, 1), match='\\'>
    >>> re.search("\\\\", r"\\")
    <re.Match object; span=(0, 1), match='\\'>

### Writing a tokenizer

A tokenizer or scanner analyzes a string to categorize groups of characters. This is a useful first step in writing a compiler or interpreter.

The text categories are specified with regular expressions. The technique is to combine those into a single master regular expression and to loop over successive matches:

    from typing import NamedTuple
    import re

    class Token(NamedTuple):
        type: str
        value: int | float | str
        line: int
        column: int

    def tokenize(code):
        keywords = {'IF', 'THEN', 'ENDIF', 'FOR', 'NEXT', 'GOSUB', 'RETURN'}
        token_specification = [
            ('NUMBER',   r'\d+(\.\d*)?'),  # Integer or decimal number
            ('ASSIGN',   r':='),           # Assignment operator
            ('END',      r';'),            # Statement terminator
            ('ID',       r'[A-Za-z]+'),    # Identifiers
            ('OP',       r'[+\-*/]'),      # Arithmetic operators
            ('NEWLINE',  r'\n'),           # Line endings
            ('SKIP',     r'[ \t]+'),       # Skip over spaces and tabs
            ('MISMATCH', r'.'),            # Any other character
        ]
        tok_regex = '|'.join('(?P<%s>%s)' % pair for pair in token_specification)
        line_num = 1
        line_start = 0
        for mo in re.finditer(tok_regex, code):
            kind = mo.lastgroup
            value = mo.group()
            column = mo.start() - line_start
            if kind == 'NUMBER':
                value = float(value) if '.' in value else int(value)
            elif kind == 'ID' and value in keywords:
                kind = value
            elif kind == 'NEWLINE':
                line_start = mo.end()
                line_num += 1
                continue
            elif kind == 'SKIP':
                continue
            elif kind == 'MISMATCH':
                raise RuntimeError(f'{value!r} unexpected on line {line_num}')
            yield Token(kind, value, line_num, column)

    statements = '''
        IF quantity THEN
            total := total + price * quantity;
            tax := price * 0.05;
        ENDIF;
    '''

    for token in tokenize(statements):
        print(token)

The tokenizer produces the following output:

    Token(type='IF', value='IF', line=2, column=4)
    Token(type='ID', value='quantity', line=2, column=7)
    Token(type='THEN', value='THEN', line=2, column=16)
    Token(type='ID', value='total', line=3, column=8)
    Token(type='ASSIGN', value=':=', line=3, column=14)
    Token(type='ID', value='total', line=3, column=17)
    Token(type='OP', value='+', line=3, column=23)
    Token(type='ID', value='price', line=3, column=25)
    Token(type='OP', value='*', line=3, column=31)
    Token(type='ID', value='quantity', line=3, column=33)
    Token(type='END', value=';', line=3, column=41)
    Token(type='ID', value='tax', line=4, column=8)
    Token(type='ASSIGN', value=':=', line=4, column=12)
    Token(type='ID', value='price', line=4, column=15)
    Token(type='OP', value='*', line=4, column=21)
    Token(type='NUMBER', value=0.05, line=4, column=23)
    Token(type='END', value=';', line=4, column=27)
    Token(type='ENDIF', value='ENDIF', line=5, column=4)
    Token(type='END', value=';', line=5, column=9)

[ Frie09 ]

Friedl, Jeffrey. Mastering Regular Expressions. 3rd ed., O'Reilly Media, 2009. The third edition of the book no longer covers Python at all, but the first edition covered writing good regular expression patterns in great detail.