Skip to content

建立 2026-09-15 更新 2026-09-15

群組與回溯

括號做兩件事:決定量詞作用在哪一段,以及把匹配到的片段存起來之後再用。

捕獲群組 (...)

由左到右編號,從 1 開始。Match.group(0) 是整段匹配,group(1) 是第一組。

import re

m = re.search(r"(\d{4})-(\d{2})-(\d{2})", "開會 2026-09-15")
print(m.group(0))  # 2026-09-15
print(m.group(1))  # 2026
print(m.groups())  # ('2026', '09', '15')

具名群組 (?P<name>...)

編號仍然在,另外可用名字取:

import re

m = re.search(
    r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})",
    "開會 2026-09-15",
)
print(m.group("year"), m.group("month"), m.group("day"))
print(m.groupdict())
# {'year': '2026', 'month': '09', 'day': '15'}

非捕獲 (?:...)

只要分組、不要佔一個 group(n)。擇一或重複一整塊時很常用:

import re

print(re.findall(r"(?:https?://)?vcdemy\.com", "vcdemy.com https://vcdemy.com"))

回溯引用

同一模式裡用 \1\2 指「前面那一組實際匹配到的文字」。取代時用 \g<1>\g<name> 比較不容易跟後面的數字黏在一起。

import re

# 找連續重複的單字
text = "that that is is a problem"
print(re.findall(r"\b(\w+)\s+\1\b", text))  # ['that', 'is']

# 把 2026-09-15 改成 15/09/2026
print(re.sub(
    r"(?P<y>\d{4})-(?P<m>\d{2})-(?P<d>\d{2})",
    r"\g<d>/\g<m>/\g<y>",
    "日期 2026-09-15",
))

\1 不是「再套一次同樣的模式」,而是「必須再出現一模一樣的字」。

先行/後行斷言

斷言也是位置條件,不把檢查到的字吃進匹配:

寫法 意義
(?=...) 後面接著要像這樣(肯定先行)
(?!...) 後面不能像這樣(否定先行)
(?<=...) 前面要像這樣(肯定後行;Python 要求長度固定)
(?<!...) 前面不能像這樣
import re

prices = "USD 12 TWD 30 USD 5"
# 只要 USD 後面的數字,不含 USD 本身
print(re.findall(r"(?<=USD )\d+", prices))  # ['12', '5']

後行斷言在 Python 裡必須是固定長度,不能寫 (?<=USD\s+)。較複雜的條件,用捕獲群組再在 Python 裡過濾通常比較清楚。

相關資料