正则表达式是处理字符串的强大工具,Python 中的 re 模块提供了对正则表达式的完整支持。本文将系统梳理 re 模块核心知识点、基础语法,并结合实际开发中的常见场景,提供可直接复用的匹配案例,帮助大家快速掌握并应用正则表达式。
一、正则表达式基础语法(核心元字符)
正则表达式的核心是元字符,它们赋予普通字符特殊的匹配能力。以下是开发中最常用的元字符及语法,按功能分类整理:
| 元字符 | 含义说明 | 示例 & 匹配效果 |
|---|---|---|
. | 匹配任意单个字符(除换行符 \n) | a.c → 匹配 abc、a1c、a c |
^ | 匹配字符串开头 | ^hello → 匹配 hello world 开头的 hello |
$ | 匹配字符串结尾 | world$ → 匹配 hello world 结尾的 world |
* | 匹配前面的字符 0 次或多次 | ab* → 匹配 a、ab、abb... |
+ | 匹配前面的字符 1 次或多次 | ab+ → 匹配 ab、abb...(不匹配 a) |
? | 匹配前面的字符 0 次或 1 次 | ab? → 匹配 a、ab(不匹配 abb) |
{n} | 匹配前面的字符恰好 n 次 | ab{2} → 仅匹配 abb |
{n,} | 匹配前面的字符至少 n 次 | ab{2,} → 匹配 abb、abbb... |
{n,m} | 匹配前面的字符 n 到 m 次 | ab{1,3} → 匹配 ab、abb、abbb |
[] | 字符集,匹配其中任意一个字符 | [abc] → 匹配 a/b/c;[0-9] → 匹配数字 |
[^] | 否定字符集,匹配不在其中的字符 | [^0-9] → 匹配非数字字符 |
| \ | 或,匹配左右任意一个表达式 | a\b → 匹配 a 或 b |
() | 分组,将括号内的内容作为一个整体 | (ab)+ → 匹配 ab、abab... |
\d | 匹配数字(等价于 [0-9]) | \d{3} → 匹配 3 位数字 |
\b | 匹配单词边界 | \bcat\b → 匹配独立的 cat |
二、Python re 模块核心方法
Python 的 re 模块封装了操作正则表达式的核心函数,以下是 5 个最常用的方法,包含功能说明、语法及实战示例:
1. re.match():从字符串开头匹配
功能:仅匹配字符串的起始位置,匹配成功返回 Match 对象,否则返回 None。
示例代码:
import re
# 匹配开头的 "hello"
result = re.match(r"hello", "hello world")
if result:
print(result.group()) # 输出:hello
# 开头不是 "hi",匹配失败
result2 = re.match(r"hi", "hello world")
print(result2) # 输出:None2. re.search():匹配字符串任意位置的第一个结果
功能:扫描整个字符串,找到第一个符合条件的匹配项,返回Match 对象,否则返回 None(区别于 match(),不局限于开头)。
示例代码:
import re
# 匹配任意位置的 "world"
result = re.search(r"world", "hello world, hello python")
if result:
print(result.group()) # 输出:world3. re.findall():获取所有匹配结果(最常用)
功能:扫描整个字符串,收集所有符合条件的子串,返回由子串组成的列表。
示例代码:
import re
# 提取所有数字
text = "手机号:13812345678,身份证:110101199001011234"
nums = re.findall(r"\d+", text)
print(nums) # 输出:['13812345678', '110101199001011234']4. re.sub():替换匹配内容
功能:将匹配到的子串替换为指定内容,返回替换后的字符串。
语法:re.sub(pattern, repl, string, count=0),其中 count=0 表示替换所有匹配项。
示例代码:
import re
# 替换所有数字为 *
text = "手机号:13812345678"
new_text = re.sub(r"\d", "*", text)
print(new_text) # 输出:手机号:***********
# 只替换前3位数字
new_text2 = re.sub(r"\d", "*", text, count=3)
print(new_text2) # 输出:手机号:***123456785. re.compile():预编译正则表达式(提升效率)
功能:将正则表达式字符串编译为 Pattern 对象,可重复使用(适合多次匹配同一正则的场景,减少重复编译开销)。
示例代码:
import re
# 预编译:匹配手机号(11位,以1开头)
phone_pattern = re.compile(r"1[3-9]\d{9}")
# 重复使用编译后的对象
text1 = "我的手机号:13812345678"
text2 = "他的手机号:15998765432"
print(phone_pattern.findall(text1)) # 输出:['13812345678']
print(phone_pattern.findall(text2)) # 输出:['15998765432']三、常见匹配场景(实战案例)
以下是开发中高频出现的正则匹配需求,包含完整代码,可直接复制复用:
1. 匹配手机号(11位,以13/14/15/17/18/19开头)
import re
pattern = r"1[3-9]\d{9}"
text = "联系电话:13812345678(正确),12345678901(错误)"
phones = re.findall(pattern, text)
print(phones) # 输出:['13812345678']2. 匹配邮箱(支持字母、数字、下划线、连字符,多域名后缀)
import re
pattern = r"[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+"
text = "邮箱:test@163.com(正确),test@.com(错误),test-123@qq.com(正确)"
emails = re.findall(pattern, text)
print(emails) # 输出:['test@163.com', 'test-123@qq.com']3. 匹配身份证号(18位,最后一位可为X/x)
import re
pattern = r"\d{17}[\dXx]"
text = "身份证:110101199001011234(正确),11010119900101123X(正确),123456(错误)"
ids = re.findall(pattern, text)
print(ids) # 输出:['110101199001011234', '11010119900101123X']4. 匹配URL(以http/https开头)
import re
pattern = r"https?://[^\s]+"
text = "链接:https://www.baidu.com(正确),http://github.com(正确),www.baidu.com(错误)"
urls = re.findall(pattern, text)
print(urls) # 输出:['https://www.baidu.com', 'http://github.com']5. 提取中文(排除数字、字母、符号)
import re
pattern = r"[\u4e00-\u9fa5]+"
text = "这是一段中文123,包含字母abc和符号!@#"
chinese = re.findall(pattern, text)
print(chinese) # 输出:['这是一段中文', '包含字母和符号']6. 去除字符串中的所有空白字符(空格、换行、制表符)
import re
text = " 这是 一段\n带空格和换行的 文本\t "
clean_text = re.sub(r"\s+", "", text)
print(clean_text) # 输出:这是一段带空格和换行的文本四、注意事项
- 原生字符串(r前缀):Python 中编写正则表达式时,建议添加
r前缀(原生字符串),避免转义字符冲突。例如r"\d"无需写成"\\d"。 贪婪匹配 vs 非贪婪匹配:
- 默认是贪婪匹配(尽可能多匹配):
a.*b匹配a123b456b时,会得到a123b456b; - 添加
?变为非贪婪匹配(尽可能少匹配):a.*?b匹配a123b456b时,会得到a123b。
- 默认是贪婪匹配(尽可能多匹配):
分组提取:使用
()分组后,可通过group(1)、group(2)等提取指定分组的内容(group(0)表示整个匹配结果):`import re- = re.search(r"姓名:(w+),年龄:(d+)", "姓名:张三,年龄:25")
print(result.group(1)) # 输出:张三
print(result.group(2)) # 输出:25`
总结
- 掌握元字符是使用正则表达式的基础,重点理解
.*+?[]()及\d\w\s等常用元字符的含义; re.findall()(查询所有)、re.sub()(替换)、re.compile()(预编译)是re模块中最实用的三个方法,覆盖大部分开发场景;- 手机号、邮箱、身份证号等高频匹配场景的正则表达式可直接复用,如需调整,可基于基础语法灵活修改。