1) 量詞 +、*、? 的基本行為
常見坑:findall(r”a*”, “aaa”) 會包含空字串(零次也算匹配)
2) 貪婪 vs 非貪婪(量詞加 ? 變非貪婪)
兩個標記之間取內容
更穩定的替代:用否定類別避免災難回溯
[^Y]* 表示「連續吃所有不是 Y 的字元」,一旦遇到 Y 就停,線性掃描、回溯很少
3) 跨行匹配與「.」
要依據換行符號切割,也可使用
multiline.splitlines()
正則表達式中的「.」用法說明:
基本功能:
「.」是萬用字元,預設匹配除換行符號(\n)以外的任意單一字元,包括字母、數字、符號和空格。
換行處理:
預設情況下「.」不匹配換行符號。如果需要匹配包含換行的任意字元,可以使用 re.DOTALL
旗標(簡寫為 re.S
)或內聯旗標 (?s)
。
字面句點匹配:
要匹配字面上的句點符號,必須使用反斜線轉義:\.
。在字元類別 [.]
中,句點會自動被視為字面字元,無需轉義。
數量控制:
.
只匹配一個字元.*
匹配零個或多個字元(貪婪模式).*?
匹配零個或多個字元(非貪婪模式)
效能建議:
避免過度使用 .*
,特別是在大文本中。可以使用更精確的字元類別(如 [a-zA-Z0-9]
)或邊界錨點。處理多行文本時,除了使用 re.S
旗標外,也可考慮 [\s\S]
作為替代方案。
實用範例:
4) ? 的多重角色(量詞、非貪婪修飾、語法)
- 量詞:a? -> 0 或 1 次
- 非貪婪:*?、+?、??、{m,n}?
- 語法(不是量詞):(?:…) 非捕獲群組、(?=…) 先行、(?!…) 否定先行、(?P<name>…) 命名群組
小例:小數點部分可選(非捕獲群組)
5) 用 re.split 做「符號切分 + 解析」
小結
量詞預設貪婪;加 ? 變非貪婪。
優先用明確類別和邊界(如 [^Y]*)抑制過吃。
跨行要用 re.S 或 [\s\S]。
抽取數字前做最小標準化,之後正則與 token 兩路並行更穩定。
推薦hahow線上學習python: https://igrape.net/30afN