字元、集合與跳脫
模式由「普通字」和「有特殊意義的符號」拼起來。普通字只匹配自己;特殊符號要嘛改寫規則,要嘛用反斜線 \ 取消特殊意義。
原始字串
Python 字串自己也會處理 \。'\n' 是換行,'\b' 是退格。正規表示式要的 \n、\b 是模式裡的特殊序列,所以模式一律用原始字串 r"...":
r"\n" 是兩個字元 \ 與 n;"\n" 才是真正的換行。模式要匹配換行時寫 r"\n" 即可,re 認得這個序列。
普通字與跳脫
hello 只匹配 hello。若要匹配特殊符號本身,在前面加 \:
| 要匹配的字 | 模式 |
|---|---|
. * + ? ^ $ | ( ) [ ] { } \ |
\. \* \+ \? \^ \$ \| \( \) \[ \] \{ \} \\ |
import re
text = "價格是 3.14 元"
print(re.findall(r"\d+\.\d+", text)) # ['3.14']
print(re.findall(r"3.14", text)) # 也能中,但 '.' 其實匹配任意一字
第二行的 3.14 會連 3x14 也算中,因為沒跳脫的 . 不是小數點。
萬用字元 .
. 匹配任意一個字元,但不含換行。要連換行一起吃,加 re.DOTALL(re.S),見 compile 與旗標。
預定義字元類
| 序列 | 意義(Python 預設 Unicode) | 取反 |
|---|---|---|
\d |
數字 | \D 非數字 |
\w |
字母、數字、底線;含許多語系的字母 | \W |
\s |
空白(空白、tab、換行等) | \S |
import re
sample = "Hi_42 你好\t2026"
print(re.findall(r"\w+", sample)) # ['Hi_42', '你好', '2026']
print(re.findall(r"\d+", sample)) # ['42', '2026']
print(re.findall(r"\s+", sample)) # [' ', '\t']
若你要的是「ASCII 數字 0–9」而不是所有 Unicode 數字,用 [0-9],或編譯時加 re.ASCII。
自訂集合 [...]
方括號裡列「這一個位置允許的字」:
[abc]:a 或 b 或 c[a-z]:小寫英文字母範圍[0-9A-F]:十六進位數字[^0-9]:開頭的^表示「不要這些」[-.]或[.-]:-放兩端才是字面減號;放中間會變成範圍
import re
phones = "0912-345-678 或 02.2345.6789"
print(re.findall(r"[0-9]{2,4}[-.][0-9]{3,4}[-.][0-9]{3,4}", phones))
集合裡多數特殊符號會失去特殊意義,但 ]、\、^(在開頭)、-(在中間)仍要小心。
擇一 |
cat|dog 匹配 cat 或 dog。| 的優先權很低,常需要括號:gr(e|a)y 才是 grey / gray。
import re
print(re.findall(r"grey|gray", "grey gray graye")) # ['grey', 'gray', 'gray']
print(re.findall(r"gr(e|a)y", "grey gray")) # 有捕獲時 findall 回傳群組
findall 碰到捕獲群組時行為會變,細節見 findall。只要擇一、不要捕獲,寫 gr(?:e|a)y。
相關資料
- 接著:量詞
- 官方:HOWTO — Simple Patterns