1. Python正则表达式基础入门
正则表达式(Regular Expression)是一种强大的文本处理工具,它使用特定语法来描述字符串的匹配模式。Python通过内置的re模块提供了完整的正则表达式功能,让我们能够高效地进行字符串搜索、替换和验证操作。
1.1 原始字符串表示法
在Python中使用正则表达式时,强烈建议使用原始字符串(raw string)表示法,即在字符串前加'r'前缀:
python复制pattern = r'\bpython\b' # 推荐使用原始字符串
pattern = '\\bpython\\b' # 不推荐,需要双重转义
原始字符串中的反斜杠不会被当作转义字符处理,这使得正则表达式更易读且不易出错。例如,\n在普通字符串中表示换行符,而在原始字符串中就是字面的反斜杠和字母n。
1.2 基本匹配方法
re模块提供了几个核心函数来进行正则匹配:
python复制import re
# 检查字符串是否匹配模式
if re.search(r'python', 'I love python'):
print("Found python!")
# 从字符串开头匹配
match = re.match(r'py', 'python')
if match:
print(f"Match at {match.start()}-{match.end()}")
# 完全匹配整个字符串
if re.fullmatch(r'python', 'python'):
print("Exact match")
2. 正则表达式语法详解
2.1 字符类与特殊序列
正则表达式提供了多种方式来匹配字符:
python复制# 字符类
re.findall(r'[aeiou]', 'python') # 匹配所有元音字母 → ['o']
re.findall(r'[^aeiou]', 'python') # 匹配非元音字母 → ['p','y','t','h','n']
# 预定义字符类
re.findall(r'\d', 'Python3.9') # 匹配数字 → ['3','9']
re.findall(r'\w', 'Python_3.9') # 匹配单词字符 → ['P','y','t','h','o','n','_','3','9']
常用特殊序列:
\d:匹配任意数字,等价于[0-9]\D:匹配任意非数字\s:匹配任意空白字符\S:匹配任意非空白字符\w:匹配任意字母数字字符\W:匹配任意非字母数字字符
2.2 重复限定符
控制模式重复次数:
python复制# 重复匹配
re.findall(r'\d+', 'a123b45') # 匹配1个或多个数字 → ['123','45']
re.findall(r'\d*', 'a123b45') # 匹配0个或多个数字 → ['','123','','45','']
re.findall(r'\d?', 'a123b45') # 匹配0个或1个数字 → ['','1','2','3','','4','5','']
re.findall(r'\d{2}', 'a123b45') # 匹配恰好2个数字 → ['12','45']
re.findall(r'\d{2,4}', 'a12345b6789') # 匹配2到4个数字 → ['1234','6789']
2.3 分组与捕获
使用圆括号创建捕获组:
python复制match = re.match(r'(\w+)@(\w+)\.com', 'user@example.com')
if match:
print(f"Username: {match.group(1)}") # user
print(f"Domain: {match.group(2)}") # example
3. 高级正则表达式技巧
3.1 非捕获组与命名组
python复制# 非捕获组(?:...)
re.findall(r'(?:\d{3}-)?\d{3}-\d{4}', '555-1234 123-555-1234')
# → ['555-1234', '123-555-1234']
# 命名组(?P<name>...)
match = re.match(r'(?P<first>\w+) (?P<last>\w+)', 'John Doe')
if match:
print(match.group('first')) # John
print(match.group('last')) # Doe
3.2 零宽断言
零宽断言允许我们在不消耗字符的情况下进行匹配:
python复制# 正向先行断言(?=...)
re.findall(r'\w+(?=ing)', 'running jumping swimming') # ['runn', 'jump', 'swimm']
# 负向先行断言(?!...)
re.findall(r'\d{3}(?!-)', '123- 456 789') # ['456', '789']
# 正向后行断言(?<=...)
re.findall(r'(?<=\$)\d+', 'Price: $100, $200') # ['100', '200']
# 负向后行断言(?<!...)
re.findall(r'(?<!\$)\d+', 'Price: $100, 200') # ['200']
4. 实用正则表达式示例
4.1 常见模式匹配
python复制# 匹配电子邮件
email_pattern = r'[\w.-]+@[\w.-]+\.\w+'
re.findall(email_pattern, 'Contact: user@example.com, admin@site.org')
# 匹配URL
url_pattern = r'https?://(?:www\.)?[\w.-]+\.\w+'
re.findall(url_pattern, 'Visit https://www.python.org')
# 匹配日期
date_pattern = r'\d{4}-\d{2}-\d{2}'
re.findall(date_pattern, 'Today is 2023-05-15')
4.2 字符串清洗与提取
python复制# 提取HTML标签内容
html = '<h1>Title</h1><p>Content</p>'
re.findall(r'<[^>]+>(.*?)</[^>]+>', html) # ['Title', 'Content']
# 移除多余空白
text = ' Hello World \n'
cleaned = re.sub(r'\s+', ' ', text).strip() # 'Hello World'
# 分割复杂字符串
data = 'name=John;age=30;city=NY'
dict(re.findall(r'(\w+)=(\w+)', data)) # {'name': 'John', 'age': '30', 'city': 'NY'}
5. 性能优化与最佳实践
5.1 预编译正则表达式
对于频繁使用的模式,预编译可以显著提高性能:
python复制# 一次性编译
pattern = re.compile(r'\bpython\b', re.IGNORECASE)
# 多次使用
if pattern.search('Learning Python'):
print("Found Python")
5.2 避免回溯灾难
某些正则表达式可能导致性能问题:
python复制# 灾难性回溯示例(避免使用)
dangerous = r'(a+)+b' # 对'aaaaaaaaac'会非常慢
# 改进版本
better = r'a+b' # 线性时间复杂度
5.3 常用标志参数
re.IGNORECASE或re.I:忽略大小写re.MULTILINE或re.M:多行模式re.DOTALL或re.S:使.匹配包括换行符在内的所有字符re.VERBOSE或re.X:允许编写带注释的正则表达式
python复制# 使用多个标志
pattern = re.compile(r"""
^ # 字符串开始
[\w\.-]+ # 用户名
@ # @符号
[\w\.-]+ # 域名
\. # 点
\w+ # 顶级域名
$ # 字符串结束
""", re.VERBOSE | re.IGNORECASE)
6. 常见问题与调试技巧
6.1 调试复杂正则表达式
python复制# 使用re.DEBUG标志查看解析过程
re.compile(r'\d{3}-\d{4}', re.DEBUG)
# 分步测试复杂模式
pattern = r'^(\w+)(?:\s+(\w+))?$'
test_cases = ['John', 'John Doe', '123']
for case in test_cases:
print(f"Testing '{case}':", re.match(pattern, case).groups())
6.2 处理Unicode字符
python复制# 匹配中文字符
re.findall(r'[\u4e00-\u9fff]+', '中文测试English混合') # ['中文测试']
# 匹配表情符号
re.findall(r'[\U0001F600-\U0001F64F]', 'Hello 😊 World') # ['😊']
6.3 性能测试与优化
python复制import timeit
setup = "import re; pattern = re.compile(r'\d{3}-\d{3}-\d{4}')"
stmt = "pattern.match('123-456-7890')"
time = timeit.timeit(stmt, setup, number=100000)
print(f"匹配耗时: {time:.4f}秒/10万次")
正则表达式是每个Python开发者都应该掌握的强大工具。通过理解其核心概念、熟悉常用模式并遵循最佳实践,你可以高效处理各种文本处理任务。记住从简单开始,逐步构建复杂模式,并始终考虑性能和可读性。
