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 等预定义类和分组,即可覆盖大部分文本处理需求;复杂模式建议先用在线工具调试再写入代码。

笔记加载中…