Python 正则表达式完全指南
正则表达式(Regular Expression)是Python中进行文本处理的强大工具。本指南将详细介绍Python中正则表达式的使用方法和实践技巧。
1. 基础知识
1.1 导入正则表达式模块
```python
import re
```
1.2 创建正则表达式
在Python中有两种方式创建正则表达式:
```python
方式1:使用原始字符串(推荐)
pattern = r'\d+'
方式2:普通字符串(需要额外转义)
pattern = '\\d+'
```
1.3 基本匹配方法
```python
import re
text = "Hello, my phone is 123-456-7890"
1. re.match() - 从字符串开始处匹配
result = re.match(r'\w+', text)
print(result.group()) # 输出: Hello
2. re.search() - 搜索整个字符串中的第一个匹配
result = re.search(r'\d+', text)
print(result.group()) # 输出: 123
3. re.findall() - 找到所有匹配项
result = re.findall(r'\d+', text)
print(result) # 输出: ['123', '456', '7890']
4. re.finditer() - 返回迭代器
for match in re.finditer(r'\d+', text):
print(f"Found {match.group()} at position {match.start()}-{match.end()}")
```
2. 正则表达式语法
2.1 字符匹配
```python
示例文本
text = "Python3 is awesome! Price: $99.99"
匹配单个字符
re.findall(r'.', text) # 匹配任意字符
re.findall(r'\d', text) # 匹配数字
re.findall(r'\D', text) # 匹配非数字
re.findall(r'\w', text) # 匹配字母/数字/下划线
re.findall(r'\W', text) # 匹配非字母/数字/下划线
re.findall(r'\s', text) # 匹配空白字符
re.findall(r'\S', text) # 匹配非空白字符
```
2.2 数量词
```python
文本示例
text = "Python programming is fun!!!"
常用数量词
re.search(r'o*', text) # 匹配0次或多次
re.search(r'o+', text) # 匹配1次或多次
re.search(r'o?', text) # 匹配0次或1次
re.search(r'o{2}', text) # 精确匹配2次
re.search(r'o{1,3}', text) # 匹配1到3次
```
2.3 字符类
```python
text = "The quick brown fox jumps over the lazy dog."
使用字符类
re.findall(r'[aeiou]', text) # 匹配所有元音字母
re.findall(r'[^aeiou]', text) # 匹配所有非元音字母
re.findall(r'[a-z]', text) # 匹配所有小写字母
re.findall(r'[A-Z]', text) # 匹配所有大写字母
```
3. 高级特性
3.1 分组和捕获
```python
分组示例
text = "John Smith, Jane Doe, Bob Johnson"
基本分组
pattern = r'(\w+)\s(\w+)'
matches = re.findall(pattern, text)
print(matches) # 输出: [('John', 'Smith'), ('Jane', 'Doe'), ('Bob', 'Johnson')]
命名分组
pattern = r'(?P<first>\w+)\s(?P<last>\w+)'
for match in re.finditer(pattern, text):
print(f"First: {match.group('first')}, Last: {match.group('last')}")
```
3.2 前向查找和后向查找
```python
text = "Price: $100, Cost: $50"
正向前向查找
re.findall(r'\d+(?=\s*dollars)', text) # 匹配后面跟着"dollars"的数字
负向前向查找
re.findall(r'\d+(?!\s*dollars)', text) # 匹配后面不跟"dollars"的数字
正向后向查找
re.findall(r'(?<=\)\\d+', text) # 匹配前面有的数字
负向后向查找
re.findall(r'(?<!\)\\d+', text) # 匹配前面没有的数字
```
4. 实用示例
4.1 数据验证
```python
def validate_email(email):
"""验证电子邮件地址"""
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
return bool(re.match(pattern, email))
def validate_phone(phone):
"""验证中国手机号"""
pattern = r'^1[3-9]\d{9}$'
return bool(re.match(pattern, phone))
def validate_password(password):
"""验证密码强度(至少8位,包含大小写字母和数字)"""
pattern = r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$'
return bool(re.match(pattern, password))
```
4.2 文本处理
```python
def extract_urls(text):
"""提取文本中的URL"""
pattern = r'https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+'
return re.findall(pattern, text)
def clean_text(text):
"""清理文本(删除多余空白字符)"""
return re.sub(r'\s+', ' ', text).strip()
def extract_dates(text):
"""提取日期(支持多种格式)"""
pattern = r'\d{4}[-/]\d{1,2}[-/]\d{1,2}|\d{1,2}[-/]\d{1,2}[-/]\d{4}'
return re.findall(pattern, text)
```
5. 性能优化技巧
5.1 编译正则表达式
```python
当需要多次使用同一个正则表达式时,应该编译它
pattern = re.compile(r'\d+')
使用编译后的正则表达式
text = "123 456 789"
matches = pattern.findall(text)
```
5.2 优化技巧
- 使用非捕获组 `(?:)`:当不需要捕获结果时
```python
不好的写法
pattern = r'(https?://)(.*)'
好的写法
pattern = r'(?:https?://)(.*)'
```
- 避免过度使用通配符
```python
不好的写法
pattern = r'.*foo.*'
好的写法
pattern = r'[^/]*foo[^/]*'
```
6. 常见问题和解决方案
6.1 贪婪vs非贪婪匹配
```python
text = "<p>First</p><p>Second</p>"
贪婪匹配(默认)
re.findall(r'<p>.*</p>', text) # 匹配整个字符串
非贪婪匹配
re.findall(r'<p>.*?</p>', text) # 分别匹配每个标签
```
6.2 处理特殊字符
```python
转义特殊字符
def escape_special_chars(text):
return re.escape(text)
示例
pattern = re.escape('hello.world') # 将点号转义
```
7. 调试技巧
```python
使用verbose模式使正则表达式更易读
pattern = re.compile(r"""
\d+ # 匹配数字
\s* # 可选的空白字符
[a-zA-Z]+ # 匹配字母
""", re.VERBOSE)
使用re.DEBUG标志查看编译信息
pattern = re.compile(r'\d+\s*[a-zA-Z]+', re.DEBUG)
```
总结
Python的正则表达式功能强大且灵活,掌握它可以大大提高文本处理效率。关键点:
-
合理使用原始字符串(r'')
-
需要重复使用时记得编译正则表达式
-
注意贪婪vs非贪婪匹配
-
适当使用命名分组提高代码可读性
-
考虑性能优化
-
编写复杂正则表达式时使用verbose模式
记住:编写正则表达式时应该遵循"简单够用"的原则,过于复杂的正则表达式往往会带来维护困难和性能问题。