正则表达式
问题
Python 正则表达式怎么用?常用模式和技巧有哪些?
答案
基础用法
import re
# 匹配
result = re.match(r"^\d+", "123abc") # 从头匹配
result = re.search(r"\d+", "abc123") # 任意位置搜索
results = re.findall(r"\d+", "a1b2c3") # 所有匹配:['1', '2', '3']
# 替换
text = re.sub(r"\d+", "X", "a1b2c3") # "aXbXcX"
# 分割
parts = re.split(r"[,;\s]+", "a,b; c d") # ['a', 'b', 'c', 'd']
# 预编译(重复使用时性能更好)
pattern = re.compile(r"\b\w+@\w+\.\w+\b")
emails = pattern.findall("联系 alice@example.com 或 bob@test.org")
分组与命名组
# 捕获组
m = re.search(r"(\d{4})-(\d{2})-(\d{2})", "日期: 2026-03-28")
m.group(0) # "2026-03-28"(整体)
m.group(1) # "2026"
m.groups() # ('2026', '03', '28')
# 命名组
m = re.search(r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})", "2026-03-28")
m.group("year") # "2026"
m.groupdict() # {'year': '2026', 'month': '03', 'day': '28'}
常用模式
| 模式 | 正则 | 示例 |
|---|---|---|
| 手机号 | r"1[3-9]\d{9}" | 13812345678 |
| 邮箱 | r"\b[\w.+-]+@[\w-]+\.[\w.-]+\b" | user@example.com |
| IP 地址 | r"\d{1,3}(\.\d{1,3}){3}" | 192.168.1.1 |
| URL | r"https?://[\w\-._~:/?#\[\]@!$&'()*+,;=]+" | https://example.com |
贪婪 vs 非贪婪
text = "<h1>标题</h1>"
re.findall(r"<.*>", text) # ['<h1>标题</h1>'] — 贪婪,尽可能多匹配
re.findall(r"<.*?>", text) # ['<h1>', '</h1>'] — 非贪婪(加 ?)
常见面试问题
Q1: re.match 和 re.search 的区别?
答案:
match:只在字符串开头匹配search:在字符串任意位置搜索第一个匹配
re.match(r"\d+", "abc123") # None(开头不是数字)
re.search(r"\d+", "abc123") # <Match '123'>
Q2: 如何避免正则表达式性能问题?
答案:
- 预编译:
re.compile()避免重复编译 - 避免回溯灾难:不要嵌套量词如
(a+)+ - 使用非捕获组:
(?:...)不需要捕获时性能更好 - 优先用字符串方法:简单操作用
str.startswith()、str.replace()等