Contents

[Python]正規化complie用法

Python 的 re 模組提供兩種使用正規表達式的方式:直接呼叫模組函式(如 re.match())或先用 re.compile() 預先編譯正規表達式再使用。本文說明 re.compile() 的用法和其優勢。

兩種使用方式比較

方式一:直接使用模組函式

1
2
3
4
5
6
7
8
import re

text = "Hello, World! 123"

# 每次呼叫都會重新編譯正規表達式
result = re.match(r'\d+', text)
result2 = re.search(r'\d+', text)
result3 = re.findall(r'\d+', text)

方式二:使用 re.compile() 預先編譯

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import re

text = "Hello, World! 123"

# 預先編譯,建立 Pattern 物件
pattern = re.compile(r'\d+')

# 使用 Pattern 物件執行匹配
result = pattern.match(text)
result2 = pattern.search(text)
result3 = pattern.findall(text)

re.compile() 的優勢

1. 效能提升(最主要原因)

當同一個正規表達式需要重複使用多次時,re.compile() 可以顯著提升效能。Python 的 re 模組雖然有內建快取,但快取大小有限(預設 512 個),compile() 可以確保編譯結果被保留。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import re
import time

data_list = ["abc123", "def456", "ghi789"] * 100000

# 方式一:每次重新解析(較慢)
start = time.time()
for text in data_list:
    re.search(r'\d+', text)
print(f"直接使用: {time.time() - start:.3f}s")

# 方式二:預先編譯(較快)
pattern = re.compile(r'\d+')
start = time.time()
for text in data_list:
    pattern.search(text)
print(f"compile後: {time.time() - start:.3f}s")

2. 程式碼更清晰易讀

將正規表達式統一定義在程式頂部,方便集中管理和修改:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import re

# 集中定義所有 pattern
EMAIL_PATTERN = re.compile(r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}')
PHONE_PATTERN = re.compile(r'\d{2,4}-\d{3,4}-\d{4}')
DATE_PATTERN = re.compile(r'\d{4}-\d{2}-\d{2}')

def extract_info(text):
    email = EMAIL_PATTERN.search(text)
    phone = PHONE_PATTERN.search(text)
    date = DATE_PATTERN.search(text)
    return email, phone, date

3. 支援旗標(Flags)設定

1
2
3
4
5
6
7
8
9
import re

# 忽略大小寫 + 多行模式
pattern = re.compile(r'^hello', re.IGNORECASE | re.MULTILINE)

texts = ["Hello World", "hello python", "HELLO everyone"]
for text in texts:
    if pattern.match(text):
        print(f"匹配: {text}")

常用方法

re.compile() 回傳的 Pattern 物件支援以下方法:

方法 說明
pattern.match(string) 從字串開頭開始匹配
pattern.search(string) 搜尋字串中任意位置的匹配
pattern.findall(string) 找出所有匹配,回傳串列
pattern.finditer(string) 找出所有匹配,回傳迭代器
pattern.sub(repl, string) 取代匹配的字串
pattern.split(string) 以匹配結果分割字串

何時使用 re.compile()

  • 應該使用:同一個正規表達式需要重複使用(迴圈、多次呼叫)
  • 可以不用:只在一個地方用一次,直接 re.search() 即可,程式碼更簡潔