Python3 正则表达式
正则表达式(regex)用一段"模式串"在文本中查找、提取、替换内容,例如从大段文字里找出所有手机号或邮箱。Python 通过 re 模块使用它,建议把模式写成 r'\d+' 这类原始字符串,避免转义混乱。
re 常用函数
import re
s = "hello 123 world 456"
print(re.findall(r'\d+', s)) # 找全部,输出:['123', '456']
print(re.search(r'\d+', s).group()) # 搜第一个,输出:123
print(re.match(r'hello', s)) # 从开头匹配成功,返回对象
print(re.match(r'world', s)) # 输出:None(开头不匹配)
print(re.sub(r'\d+', '#', s)) # 替换,输出:hello # world #
print(re.split(r'\s+', s)) # 输出:['hello', '123', 'world', '456']
print([m.group() for m in re.finditer(r'\d+', s)]) # finditer 输出:['123', '456']
元字符与转义
| 元字符 | 含义 |
|---|---|
| . | 匹配任意一个字符(除换行) |
| ^ $ | 分别匹配开头、结尾 |
| | | 或,如 a|b |
| \ | 转义字符 |
| [ ] | 字符类 |
| ( ) | 分组 |
要匹配元字符本身须转义,如匹配小数点用 .:re.findall(r'.', '3.14.com') 会得到两个点号。
字符类与预定义字符类
[...] 表示"其中之一";预定义类 \d 等价 [0-9]、\w 等价 [A-Za-z0-9_]、\s 匹配空白、\b 是单词边界:
import re
print(re.findall(r'[abc]+', 'a1b2cc')) # 输出:['a', 'b', 'cc']
print(re.findall(r'\d', 'a1b2')) # 输出:['1', '2']
print(re.findall(r'\w+', 'hello_world!')) # 输出:['hello_world']
print(re.findall(r'\bcat\b', 'a cat, catalog')) # 输出:['cat']
数量词:贪婪与懒惰
| 数量词 | 含义 |
|---|---|
| * | 前一个字符出现 0 次或多次 |
| + | 出现 1 次或多次 |
| ? | 出现 0 次或 1 次 |
| {m, n} | 出现 m 到 n 次 |
默认贪婪匹配尽可能长,后面加 ? 变懒惰、尽可能短:
import re
s = '<b>hello</b> and <b>world</b>'
print(re.findall(r'<b>.*</b>', s)) # 贪婪,输出:['<b>hello</b> and <b>world</b>']
print(re.findall(r'<b>.*?</b>', s)) # 懒惰,输出:['<b>hello</b>', '<b>world</b>']
分组与命名组
用括号分组后 group(n) 取内容;?P<名字> 给组命名,提取更直观:
import re
m = re.search(r'(\d{4})-(\d{2})-(\d{2})', '日期 2025-01-06')
print(m.group(1), m.group(2), m.group(3)) # 输出:2025 01 06
m2 = re.search(r'(?P<year>\d{4})-(?P<month>\d{2})', '2025-01')
print(m2.group('year'), m2.group('month')) # 输出:2025 01
手机号与邮箱匹配示例
import re
print(re.match(r'^1\d{10}$', '13812345678')) # 输出:<re.Match object; ...>
print(re.match(r'^1\d{10}$', '23812345678')) # 输出:None
text = '联系 a@b.com 或 x@y.cn'
print(re.findall(r'\w+@\w+\.\w+', text)) # 输出:['a@b.com', 'x@y.cn']
print(re.findall(r'python', 'I love PYTHON', re.IGNORECASE)) # 输出:['PYTHON']
compile 编译复用
反复使用的模式先 compile 成对象,性能更好、代码更整洁:
import re
phone = re.compile(r'^1\d{10}$')
print(phone.match('13812345678')) # 输出:<re.Match object; ...>
print(phone.match('12345')) # 输出:None
小结
先会用 findall 提取、search 查找、sub 替换,再掌握 \d \w \s 等预定义类和分组,即可覆盖大部分文本处理需求;复杂模式建议先用在线工具调试再写入代码。