【Python 筆記】正規運算式(Regular Expression)
【Python 筆記】正規運算式(Regular Expression)
感謝您點進本篇文章,本篇文章為我 LukeTseng 個人首篇 Python 筆記系列文章,主要記錄我個人學習軌跡,所有內容皆用於個人學習用途,斟酌參考。若文章有任意處有誤,煩請各位指點,謝謝。
簡介
這東西的名字很多,有什麼正規表達式、正規表示法、規則運算式、常規表示法等等,我個人比較習慣叫他是正規運算式,總之他的名字就是 Regular Expression(簡稱 RE、regex)就對了,在這之後我都叫他是 regex 縮寫。
regex 是一套用來描述和比對字串樣式規則的「語法」或「表示法」,通常被嵌入在各大程式語言當中,例如我們最愛用的 Python 就是其一。regex 在處理和解析字串方面十分強大,因此也是我們要學習的對象。
你可能想說在 notepad 裡面就可以用搜尋、取代這些功能了,為什麼還需要 regex?因為 regex 他不只是只有搜尋、取代這些功能而已,他還有篩選的功能,例如可以篩出特定字元、字串,以此來找到電子郵件格式及電話號碼。
在 Python 使用 regex
1 | import re |
Python 本身就有內建 regex,因此只要直接引入就好了。
編譯 regex
在做 regex 之前,都需要做編譯的動作,因此以下就是我們 regex 最基本的語法:
1 | import re |
:::info
建議在 regex 字串前加上 r 讓字串轉成原始字串,這樣反斜線 \ 就不會當成跳脫字元處理。
:::
而上面 'ab*' 的意思就是「必須要有一個字母 a」以及「0 個或 1 個以上的的字母 b」。
字元類別(Character Classes)
字元類別允許匹配指定集合中的任一個字元,用中括號 [] 圍起來。
常見的有以下幾種:
[abc]:匹配 a、b 或 c。[a-z]:匹配任何小寫字母。[A-Z]:匹配任何大寫字母。[0-9]:匹配任何數字。[^abc]:匹配除了 a、b、c 以外的任何字元(否定)。
特殊字元序列
\d:匹配任何數字,等同於[0-9]。\D:匹配任何非數字字元。\w:匹配任何字母、數字或底線,等同於[a-zA-Z0-9_]。\W:匹配任何非字母數字字元。\s:匹配任何空白字元(空格、tab、換行等)。\S:匹配任何非空白字元。
量詞(Quantifiers)
用來指定某個模式應出現的次數:
*:匹配前面的字元 0 次或多次。+:匹配前面的字元 1 次或多次。?:匹配前面的字元 0 次或 1 次。{n}:精確匹配 n 次。{n,}:至少匹配 n 次。{n,m}:匹配 n 到 m 次。
錨點(Anchors)
用來指定匹配在字串中的位置:
^:匹配字串的開頭。$:匹配字串的結尾。\b:匹配單詞邊界。\B:匹配非單詞邊界。
常用方法
| 方法 | 語法 | 說明 | 回傳值 |
|---|---|---|---|
re.compile() | re.compile(pattern, flags=0) | 將正規表達式編譯成模式物件,可重複使用以提升效能 | Pattern 物件 |
re.match() | re.match(pattern, string, flags=0) | 從字串開頭開始匹配,只檢查開頭是否符合模式 | Match 物件或 None |
re.search() | re.search(pattern, string, flags=0) | 掃描整個字串,尋找第一個符合模式的位置 | Match 物件或 None |
re.findall() | re.findall(pattern, string, flags=0) | 找出所有不重疊的匹配結果 | 包含所有匹配字串的列表 |
re.finditer() | re.finditer(pattern, string, flags=0) | 找出所有匹配結果,以迭代器形式回傳 | Match 物件的迭代器 |
re.sub() | re.sub(pattern, repl, string, count=0, flags=0) | 將所有符合模式的部分替換成指定字串,count 可限制替換次數 | 替換後的新字串 |
re.subn() | re.subn(pattern, repl, string, count=0, flags=0) | 與 re.sub() 類似,但會回傳替換次數 | (新字串, 替換次數) 的元組 |
re.split() | re.split(pattern, string, maxsplit=0, flags=0) | 根據符合的模式分割字串,maxsplit 可限制分割次數 | 分割後的字串列表 |
re.fullmatch() | re.fullmatch(pattern, string, flags=0) | 檢查整個字串是否完全符合模式 | Match 物件或 None |
1. re.match() 範例
re.match() 為從字串開頭開始匹配模式(pattern)的方法。如果開頭符合模式則回傳 Match 物件,否則回傳 None。
以下程式碼中的 pattern 的 ^ 符號是一個錨點(anchor),表示匹配字串的開頭位置。這個符號確保 pattern 必須從字串的最開始就符合,而不是在字串中間找到符合的部分。
^ 放在 regex 的開頭,表示 text 字串一開始就要是 Hello 否則不匹配。
:::info
在當 re.match() 或 re.search() 成功匹配時,會回傳 match 物件,這物件會提供三個方法來取得匹配資訊:
match.group():以字串形式回傳匹配到的內容。match.start():回傳匹配內容在字串中的起始位置(索引值)。match.end():回傳匹配內容的結束位置(最後一個字元的索引 + 1)。
:::
1 | import re |
Output:
1 | 字串以 'Hello' 開頭 |
2. re.search() 範例
1 | import re |
Output:
1 | 找到: Python |
3. re.findall() 範例
\d 表示任何一個數字字元,同 [0-9] 就是 0 到 9 的意思。
而 \d 再加上一個 +,表示前面的 pattern 至少要出現 1 次以上。
\d+ 整句話翻譯過來的話就是 0 到 9 的數字至少要出現 1 次以上。
re.findall() 方法會回傳一個匹配到的字串列表。
1 | import re |
Output:
1 | ['0987654321', '0912345678'] |
4. re.sub() 範例
sub 是取自 substitute 的縮寫,表示把字串交換,如下範例所示,將 Python 替換成 C++ 字串。
1 | import re |
Output:
1 | I like C++ because C++ is so powered. |
那 re.sub() 還有他的親姊妹叫做 re.subn(),兩者用法完全一樣,只差在 re.subn() 回傳一個元組,前面是替換完成的字串,後面是替換的次數,沿用上述範例:
1 | import re |
Output:
1 | ('I like C++ because C++ is so powered.', 2) |
5. re.split() 範例
re.split() 根據匹配到的 pattern 來分割字串。
以下範例展示了將 ,;: 的 pattern 分割字串,達到如內建方法 .split() 一樣的事情。但差別在於內建的 .split() 只能找到一種 pattern 而已。
1 | import re |
Output:
1 | ['apple', 'banana', 'orange', 'grape'] |
字元類別、特殊字元序列、量詞、錨點的一些例子
前面說明過了一些使用的方法,那麼就可以來講一些特殊的例子來玩玩看了。
[^0-9] 除了 0 到 9 以外的字元:
1 | import re |
Output:
1 | ['a', 'b', 'c'] |
\w+ 匹配任何字母、數字或底線:
1 | import re |
Output:
1 | ['他說了', '在某種語言中'] |
*、?、{n, m} 範例:
1 | import re |
Output:
1 | ['a', 'ab', 'abb', 'abbb'] |
$、\b 範例:
1 | import re |
一些小應用
1. 電子郵件驗證
1 | import re |
2. 電話號碼擷取
1 | import re |
Output:
1 | 找到: ['02-1234-5678'] |
3. 資料擷取
1 | import re |
Output:
1 | ['https://example.com', 'https://test.com', '/local/path'] |
4. 密碼強度驗證
1 | import re |
Output:
1 | (False, '密碼長度至少需要 8 個字元') |
Regex 線上除錯工具
網路上隨便找就有了,這邊推薦兩個網站:
- regex101.com
- regexr.com
輸入自己的 Regex 就可以在他的測試文件裡面知道哪些資料是被篩選的。
當在設計複雜的 Regex 的時候,就可以用這個試試看。
總結
基礎語法架構:
- 字元類別:
[abc]、[a-z]、[0-9]等用於匹配指定集合中的字元。 - 特殊字元序列:
\d(數字)、\w(字母數字底線)、\s(空白字元)。 - 量詞:
*(0次或多次)、+(1次或多次)、?(0次或1次)、{n,m}控制出現次數。 - 錨點:
^(字串開頭)、$(字串結尾)、\b(單詞邊界)等定位符號。
常用方法表:
| 方法 | 語法 | 說明 | 回傳值 |
|---|---|---|---|
re.compile() | re.compile(pattern, flags=0) | 將正規表達式編譯成模式物件,可重複使用以提升效能 | Pattern 物件 |
re.match() | re.match(pattern, string, flags=0) | 從字串開頭開始匹配,只檢查開頭是否符合模式 | Match 物件或 None |
re.search() | re.search(pattern, string, flags=0) | 掃描整個字串,尋找第一個符合模式的位置 | Match 物件或 None |
re.findall() | re.findall(pattern, string, flags=0) | 找出所有不重疊的匹配結果 | 包含所有匹配字串的列表 |
re.finditer() | re.finditer(pattern, string, flags=0) | 找出所有匹配結果,以迭代器形式回傳 | Match 物件的迭代器 |
re.sub() | re.sub(pattern, repl, string, count=0, flags=0) | 將所有符合模式的部分替換成指定字串,count 可限制替換次數 | 替換後的新字串 |
re.subn() | re.subn(pattern, repl, string, count=0, flags=0) | 與 re.sub() 類似,但會回傳替換次數 | (新字串, 替換次數) 的元組 |
re.split() | re.split(pattern, string, maxsplit=0, flags=0) | 根據符合的模式分割字串,maxsplit 可限制分割次數 | 分割後的字串列表 |
re.fullmatch() | re.fullmatch(pattern, string, flags=0) | 檢查整個字串是否完全符合模式 | Match 物件或 None |
參考資料
Regular Expression HOWTO — Python 3.14.0 documentation
Python 規則運算式 | Python Education | Google for Developers
Mastering Python RegEx: A Deep Dive into Pattern Matching - StrataScratch




