《七个Python正则表达式使用示例》
正则表达式(Regular Expression)是处理字符串的强大工具,通过定义模式匹配规则,可以高效地完成搜索、替换、验证等操作。Python中的`re`模块提供了完整的正则表达式支持,本文将通过七个典型示例,详细讲解其在实际开发中的应用场景与实现方法。
一、基础匹配:提取电子邮件地址
电子邮件地址的格式通常为`用户名@域名`,其中用户名可包含字母、数字、点、下划线等,域名由点分隔的多级子域名组成。通过正则表达式可以快速提取文本中的所有邮箱。
import re
text = "联系我:test@example.com,或发送邮件至support@domain.co.uk"
pattern = r'\b[\w.-]+@[\w.-]+\.\w+\b'
emails = re.findall(pattern, text)
print(emails) # 输出: ['test@example.com', 'support@domain.co.uk']
模式解释:
- `\b`:单词边界,确保匹配完整邮箱
- `[\w.-]+`:匹配用户名(字母、数字、下划线、点、横线)
- `@`:直接匹配符号
- `[\w.-]+\.\w+`:匹配域名(至少两级,如`example.com`)
二、分组捕获:解析URL参数
URL查询字符串(如`?name=John&age=25`)中的参数可通过分组提取键值对。使用`re.finditer`结合分组实现动态解析。
url = "https://example.com/path?name=John&age=25&city=NY"
pattern = r'[?&]([^=]+)=([^&]+)'
params = {}
for match in re.finditer(pattern, url):
key, value = match.groups()
params[key] = value
print(params) # 输出: {'name': 'John', 'age': '25', 'city': 'NY'}
模式解释:
- `[?&]`:匹配参数起始符(`?`或`&`)
- `([^=]+)`:第一个分组,匹配键(非等号字符)
- `=([^&]+)`:匹配等号后值(非&字符)
三、替换操作:敏感信息脱敏
在日志处理中,需隐藏用户手机号或身份证号。使用`re.sub`将中间四位替换为星号。
log = "用户138****1234于2023年登录,身份证号510***6789"
phone_pattern = r'1[3-9]\d{4}\d{4}'
id_pattern = r'\d{4}\d{4}\d{4}'
def mask_phone(match):
return match.group()[:3] + '****' + match.group()[-4:]
def mask_id(match):
return match.group()[:4] + '***' + match.group()[-4:]
log = re.sub(phone_pattern, mask_phone, log)
log = re.sub(id_pattern, mask_id, log)
print(log) # 输出: 用户138****1234于2023年登录,身份证号510***6789
技巧说明:通过回调函数实现动态替换,比静态替换更灵活。
四、非贪婪匹配:提取HTML标签内容
处理HTML时,需提取`
html = "
第一段
第二段
"
pattern = r'(.*?)
'
contents = re.findall(pattern, html)
print(contents) # 输出: ['第一段', '第二段']
关键点:`.*?`表示匹配尽可能少的字符,直到遇到第一个`
`。五、预编译模式:高效重复匹配
若需多次使用同一正则表达式,预编译(`re.compile`)可提升性能。示例:验证密码复杂度。
password_rules = re.compile(r'^(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$')
passwords = ["Pass123!", "weak", "Strong@123"]
for pwd in passwords:
if password_rules.match(pwd):
print(f"{pwd}: 合法")
else:
print(f"{pwd}: 不合法")
# 输出:
# Pass123!: 合法
# weak: 不合法
# Strong@123: 合法
模式解释:
- `(?=.*[A-Z])`:正向预查,要求至少一个大写字母
- `(?=.*\d)`:要求至少一个数字
- `(?=.*[@$!%*?&])`:要求至少一个特殊字符
- `{8,}`:总长度至少8位
六、跨行匹配:提取多行日志
默认情况下,`.`不匹配换行符。通过`re.DOTALL`标志或`[\s\S]`可实现跨行匹配。
log_file = """
ERROR 2023-01-01: 文件未找到
TRACE: 尝试打开/path/to/file
WARNING: 权限不足
"""
pattern = r'ERROR[\s\S]*?WARNING'
error_block = re.search(pattern, log_file).group()
print(error_block)
# 输出:
# ERROR 2023-01-01: 文件未找到
# TRACE: 尝试打开/path/to/file
# WARNING: 权限不足
替代方案:使用`re.DOTALL`标志
pattern = r'ERROR.*?WARNING'
error_block = re.search(pattern, log_file, re.DOTALL).group()
七、命名分组:结构化提取日期
命名分组(`(?P
date_str = "会议时间:2023-12-25 14:30"
pattern = r'会议时间:(?P\d{4})-(?P\d{2})-(?P\d{2})'
match = re.search(pattern, date_str)
if match:
print(f"年: {match.group('year')}, 月: {match.group('month')}, 日: {match.group('day')}")
# 输出: 年: 2023, 月: 12, 日: 25
优势:通过名称访问分组,避免依赖分组序号。
常见问题与优化技巧
1. 编译正则表达式的时机
在循环中重复使用同一模式时,务必预编译:
# 低效方式
for _ in range(1000):
re.match(r'\d+', '123')
# 高效方式
pattern = re.compile(r'\d+')
for _ in range(1000):
pattern.match('123')
2. 避免过度匹配
错误示例:提取所有数字时误用`\d+`导致匹配意外内容。
text = "订单12345,客户ID67890"
# 错误:匹配整个字符串
print(re.findall(r'\d+', text)) # 输出: ['12345', '67890'](正确,但需注意上下文)
# 更安全的做法:限定前后字符
print(re.findall(r'订单(\d+)', text)) # 输出: ['12345']
3. 处理特殊字符
匹配包含正则元字符的字符串时,需转义:
text = "价格:$19.99"
pattern = r'\$\d+\.\d{2}' # 匹配$符号
print(re.search(pattern, text).group()) # 输出: $19.99
总结
本文通过七个实际案例,涵盖了正则表达式在Python中的核心应用场景:基础匹配、分组捕获、替换脱敏、非贪婪匹配、预编译优化、跨行处理以及命名分组。掌握这些技巧后,可高效解决字符串处理中的复杂问题。建议结合`re`模块官方文档进一步探索高级特性,如递归匹配、条件匹配等。
关键词:Python正则表达式、字符串匹配、分组捕获、非贪婪匹配、预编译模式、命名分组、敏感信息脱敏
简介:本文通过七个典型示例详细讲解Python正则表达式的使用方法,涵盖电子邮件提取、URL参数解析、敏感信息脱敏、HTML内容提取、密码验证、多行日志处理及日期结构化解析等场景,并提供性能优化与常见问题解决方案。