"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.
