擷取欄位
從自由文字抽出結構化資料時,用具名群組 + finditer。回傳字典之後,程式其他部分就不必再碰模式。
訂單編號與金額
import re
text = """
#A-1001 筆電 TWD 32900
#A-1002 滑鼠 TWD 790
備註:客人要求下週出貨
"""
ORDER = re.compile(
r"#(?P<id>A-\d{4})\s+(?P<item>\S+)\s+TWD\s+(?P<price>\d+)"
)
rows = [m.groupdict() for m in ORDER.finditer(text)]
print(rows)
# [{'id': 'A-1001', 'item': '筆電', 'price': '32900'}, ...]
total = sum(int(r["price"]) for r in rows)
print(total) # 33690
price 仍是字串,要運算再自己 int()。
從句子抽出 URL
import re
note = "講義在 https://www.vcdemy.com/regex 與 http://example.com/a 兩處。"
URL = re.compile(r"https?://[^\s]+")
print(URL.findall(note))
[^\s]+ 吃到空白為止。結尾若黏到中文標點,可再 rstrip("。,,)") 清掉。
檔名裡的日期與序號
import re
names = [
"invoice_20260915_001.pdf",
"invoice_20260916_002.pdf",
"readme.txt",
]
FILE = re.compile(
r"^invoice_(?P<day>\d{8})_(?P<seq>\d{3})\.pdf$"
)
for name in names:
m = FILE.fullmatch(name)
if m:
print(m["day"], m["seq"])
m["day"] 等價於 m.group("day")(3.6+)。
鍵值對
import re
line = "host=db01 port=5432 ssl=true"
PAIR = re.compile(r"(?P<key>[A-Za-z_]+)=(?P<value>\S+)")
config = {m["key"]: m["value"] for m in PAIR.finditer(line)}
print(config)
# {'host': 'db01', 'port': '5432', 'ssl': 'true'}
擷取失敗時
找不到就得到空清單,不要假設一定有第 0 筆:
import re
def first_year(text: str) -> str | None:
m = re.search(r"\b(19|20)\d{2}\b", text)
return m.group(0) if m else None
print(first_year("built 1999, shipped 2026")) # 1999
print(first_year("no year")) # None
相關資料
- API:findall 與 finditer
- 下一頁:批次取代
- 官方:Match Objects