群組與回溯
括號做兩件事:決定量詞作用在哪一段,以及把匹配到的片段存起來之後再用。
捕獲群組 (...)
由左到右編號,從 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)。擇一或重複一整塊時很常用:
回溯引用
同一模式裡用 \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 裡過濾通常比較清楚。
相關資料
- 上一頁:錨點與邊界
- 接到 Python:search / match、擷取範例
- 官方:HOWTO — Grouping