正则表达式进阶
正则表达式进阶
本文将深入探讨正则表达式的高级特性,包括编译优化、复杂替换操作以及贪婪与非贪婪模式的使用。
编译正则表达式
当同一个模式需要多次使用时,先编译可以提高性能:
import re
# 编译正则表达式
email_pattern = re.compile(r'[\w.+-]+@[\w-]+\.[\w.]+')
# 多次使用
text1 = "联系我: test@example.com"
text2 = "邮箱: user@domain.org"
print(email_pattern.search(text1).group()) # test@example.com
print(email_pattern.findall(text2)) # ['user@domain.org']
查找与替换
import re
# sub - 替换所有匹配
text = "2024年1月15日,气温-5摄氏度"
result = re.sub(r'\d+', '#', text)
print(result) # 2024年#月#日,气温-#摄氏度
# subn - 替换并返回替换次数
result, count = re.subn(r'\d+', '#', text)
print(f"替换{count}次: {result}")
# 替换函数
def double_number(match):
return str(int(match.group()) * 2)
result = re.sub(r'\d+', double_number, "价格: 100元,数量: 5个")
print(result) # 价格: 200元,数量: 10个
# 使用lambda
result = re.sub(r'(\w+)@(\w+)', lambda m: f'{m.group(2)}@{m.group(1)}',
'a@b.com')
print(result) # b@a.com
贪婪与非贪婪
默认情况下,正则表达式是贪婪的,尽可能多地匹配:
import re
text = '<div>内容1</div><div>内容2</div>'
# 贪婪模式(默认)
greedy = re.findall(r'<div>.*</div>', text)
print(greedy) # ['<div>内容1</div><div>内容2</div>']
# 非贪婪模式 - 在量词后加 ?
non_greedy = re.findall(r'<div>.*?</div>', text)
print(non_greedy) # ['<div>内容1</div>', '<div>内容2</div>']
# 更多示例
text = 'aaa'
print(re.findall(r'a+', text)) # ['aaa'](贪婪)
print(re.findall(r'a+?', text)) # ['a', 'a', 'a'](非贪婪)
前向/后向断言
import re
# 正向前瞻 - 后面必须跟...
text = "价格: 100元"
result = re.findall(r'\d+(?=元)', text)
print(result) # ['100']
# 负向前瞻 - 后面不能跟...
text = "100元 200美元"
result = re.findall(r'\d+(?!元)', text)
print(result) # ['1', '2', '2', '0', '0']
# 正向后顾 - 前面必须是...
text = "温度: -5度"
result = re.findall(r'(?<=: )-?\d+', text)
print(result) # ['-5']
# 负向后顾 - 前面不能是...
text = "test123 test456"
result = re.findall(r'(?<!\d)\d+', text)
分组替换
import re
# 交换姓名
name = "John Smith"
swapped = re.sub(r'(\w+) (\w+)', r'\2 \1', name)
print(swapped) # Smith John
# HTML标签提取
html = '<a href="https://example.com">链接</a>'
match = re.search(r'<a href="(.*?)">(.*?)</a>', html)
if match:
print(f"链接: {match.group(1)}, 文本: {match.group(2)}")
实战:日志解析
import re
from datetime import datetime
log_pattern = re.compile(
r'(?P<time>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})'
r' \[(?P<level>\w+)\]'
r' (?P<message>.*)'
)
log = "2024-01-15 10:30:45 [ERROR] 连接失败"
match = log_pattern.search(log)
if match:
data = match.groupdict()
print(f"时间: {data['time']}")
print(f"级别: {data['level']}")
print(f"消息: {data['message']}")
掌握这些进阶技巧,能让你更高效地处理复杂的文本匹配和替换任务。