<think>我们使用Python的re模块进行正则表达式匹配。以下是一个详细的指南,包含常见操作和代码示例。
正则表达式是一种强大的字符串匹配和处理工具。Python通过re模块提供对正则表达式的支持。
主要步骤:
1. 导入re模块
2. 编写正则表达式模式
3. 选择re模块的函数(如match、search、findall等)进行匹配
4. 处理匹配结果
常用函数:
- re.match(pattern, string): 从字符串起始位置匹配,如果起始位置匹配不成功,则返回None。
- re.search(pattern, string): 扫描整个字符串并返回第一个成功的匹配。
- re.findall(pattern, string): 返回字符串中所有匹配的子串,以列表形式返回。
- re.finditer(pattern, string): 返回一个迭代器,包含所有匹配对象。
- re.sub(pattern, repl, string): 替换字符串中匹配的子串。
匹配对象(Match object)的方法:
- group(): 返回匹配的整个字符串
- groups(): 返回一个包含所有小组字符串的元组
- start(): 返回匹配开始的位置
- end(): 返回匹配结束的位置
- span(): 返回一个元组包含匹配(开始,结束)的位置
编译正则表达式(提高效率):
当同一个正则表达式被多次使用时,可以将其编译成正则表达式对象,以提高效率。
pattern = re.compile(r'pattern')
然后使用 pattern.match(), pattern.search() 等方法。
特殊字符:
. 匹配任意字符(除了换行符)
^ 匹配字符串开头
$ 匹配字符串结尾
* 匹配0次或多次
+ 匹配1次或多次
? 匹配0次或1次
{m} 匹配m次
{m,n} 匹配m到n次
[] 字符集,如[abc]匹配a、b、c
| 或,如A|B匹配A或B
() 分组
\d 匹配数字,等价于[0-9]
\D 匹配非数字
\s 匹配空白字符(空格、制表符等)
\S 匹配非空白字符
\w 匹配字母数字及下划线,等价于[a-zA-Z0-9_]
\W 匹配非字母数字及下划线
注意:在Python中,使用原始字符串(r'string')可以避免转义问题。
下面是一个完整的示例代码,展示各种常见用法:</think># Python 正则表达式字符串匹配详解
在 Python 中使用正则表达式进行字符串匹配主要通过 `re` 模块实现。下面我将详细介绍正则表达式的使用方法和常见应用场景。
## 基础正则表达式匹配
### 1. 导入 re 模块
```python
import re
```
### 2. 基本匹配方法
```python
# 示例字符串
text = "Python is a powerful programming language. Python is also versatile."
# 1. re.match() - 从字符串开头匹配
match_result = re.match(r'Python', text)
print(match_result) # <re.Match object; span=(0, 6), match='Python'>
# 2. re.search() - 搜索整个字符串
search_result = re.search(r'powerful', text)
print(search_result) # <re.Match object; span=(10, 17), match='powerful'>
# 3. re.findall() - 查找所有匹配项
all_matches = re.findall(r'Python', text)
print(all_matches) # ['Python', 'Python']
# 4. re.finditer() - 返回匹配对象迭代器
for match in re.finditer(r'Python', text):
print(f"Found '{match.group()}' at position {match.start()}-{match.end()}")
# Found 'Python' at position 0-6
# Found 'Python' at position 40-46
# 5. re.fullmatch() - 整个字符串匹配
full_match = re.fullmatch(r'.*', text)
print(full_match) # <re.Match object; span=(0, 55), match='Python is a powerful programming language. Python is also >
```
## 常用正则表达式模式
### 基本模式示例
```python
# 匹配数字
numbers = re.findall(r'\d+', "Phone: 123-4567, Cell: 987-6543")
print(numbers) # ['123', '4567', '987', '6543']
# 匹配单词
words = re.findall(r'\w+', "Hello, world! 2023")
print(words) # ['Hello', 'world', '2023']
# 匹配邮箱地址
emails = re.findall(r'[\w\.-]+@[\w\.-]+', "Contact: user@example.com, support@domain.org")
print(emails) # ['user@example.com', 'support@domain.org']
# 匹配URL
urls = re.findall(r'https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+', "Visit https://example.com or http://sub.domain.org")
print(urls) # ['https://example.com', 'http://sub.domain.org']
```
## 高级匹配技巧
### 1. 分组和捕获
```python
# 分组提取
date_text = "2023-10-25, 2024-01-15"
matches = re.findall(r'(\d{4})-(\d{2})-(\d{2})', date_text)
print(matches) # [('2023', '10', '25'), ('2024', '01', '15')]
# 命名分组
pattern = r'(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})'
match = re.search(pattern, "Event date: 2023-10-25")
if match:
print(f"Year: {match.group('year')}, Month: {match.group('month')}, Day: {match.group('day')}")
# Year: 2023, Month: 10, Day: 25
```
### 2. 非捕获组和超前/后行断言
```python
# 非捕获组 (?:...)
text = "color: red; color: blue; color: green"
colors = re.findall(r'color: (?:red|blue|green)', text)
print(colors) # ['color: red', 'color: blue', 'color: green']
# 正向前瞻 (?=...)
# 匹配后面跟着"元"的"Python"
matches = re.findall(r'Python(?=元)', "Python编程 Python元编程")
print(matches) # ['Python'] (只匹配第二个Python)
# 负向前瞻 (?!...)
# 匹配后面不是"元"的"Python"
matches = re.findall(r'Python(?!元)', "Python编程 Python元编程")
print(matches) # ['Python'] (只匹配第一个Python)
# 正向后顾 (?<=...)
# 匹配前面是"元"的"Python"
matches = re.findall(r'(?<=元)Python', "元Python编程")
print(matches) # ['Python']
# 负向后顾 (?<!...)
# 匹配前面不是"元"的"Python"
matches = re.findall(r'(?<!元)Python', "元Python 普通Python")
print(matches) # ['Python'] (只匹配第二个Python)
```
### 3. 编译正则表达式
```python
# 编译正则表达式对象(提高性能)
pattern = re.compile(r'\b[A-Z][a-z]+\b') # 匹配首字母大写的单词
text = "John Smith and Alice Johnson work at Google."
matches = pattern.findall(text)
print(matches) # ['John', 'Smith', 'Alice', 'Johnson', 'Google']
```
## 字符串操作与正则表达式
### 1. 字符串替换
```python
# 简单替换
text = "Python 2.7 and Python 3.10"
new_text = re.sub(r'Python 2\.7', 'Python 3.x', text)
print(new_text) # "Python 3.x and Python 3.10"
# 使用函数进行替换
def increment_version(match):
version = int(match.group(1))
return f"Python {version + 1}"
text = "Python 2, Python 3, Python 4"
new_text = re.sub(r'Python (\d)', increment_version, text)
print(new_text) # "Python 3, Python 4, Python 5"
```
### 2. 字符串分割
```python
text = "apple,banana;cherry|date"
parts = re.split(r'[,;|]', text)
print(parts) # ['apple', 'banana', 'cherry', 'date']
# 保留分隔符
parts = re.split(r'([,;|])', text)
print(parts) # ['apple', ',', 'banana', ';', 'cherry', '|', 'date']
```
## 实际应用案例
### 1. 验证输入格式
```python
def validate_email(email):
"""验证电子邮件地址格式"""
pattern = r'^[\w\.-]+@[\w\.-]+\.\w{2,}$'
return bool(re.match(pattern, email))
print(validate_email("user@example.com")) # True
print(validate_email("invalid.email@")) # False
print(validate_email("name@domain.co.uk")) # True
```
### 2. 提取日志信息
```python
log = """
[2023-10-25 08:30:45] INFO: User 'admin' logged in
[2023-10-25 09:15:22] ERROR: Database connection failed
[2023-10-25 10:05:33] WARNING: Disk space low
"""
pattern = r'\[(.*?)\] (\w+): (.*)'
for match in re.finditer(pattern, log):
timestamp, level, message = match.groups()
print(f"{timestamp} | {level:7} | {message}")
# 输出:
# 2023-10-25 08:30:45 | INFO | User 'admin' logged in
# 2023-10-25 09:15:22 | ERROR | Database connection failed
# 2023-10-25 10:05:33 | WARNING | Disk space low
```
### 3. 解析复杂文本
```python
html = """
<div class="product">
<h3>Product A</h3>
<p>Price: $19.99</p>
<p>Rating: 4.5/5</p>
</div>
<div class="product">
<h3>Product B</h3>
<p>Price: $29.99</p>
<p>Rating: 3.8/5</p>
</div>
"""
pattern = r'<div class="product">.*?<h3>(.*?)</h3>.*?<p>Price: \$(.*?)</p>.*?<p>Rating: (.*?)/5</p>'
products = re.findall(pattern, html, re.DOTALL)
for name, price, rating in products:
print(f"Product: {name}, Price: ${price}, Rating: {rating}/5")
# 输出:
# Product: Product A, Price: $19.99, Rating: 4.5/5
# Product: Product B, Price: $29.99, Rating: 3.8/5
```
## 性能优化与最佳实践
1. **预编译正则表达式**:对于重复使用的模式,使用 `re.compile()` 可以提高性能
2. **使用原始字符串**:在模式字符串前加 `r` 前缀(如 `r'\d+'`)避免转义问题
3. **避免贪婪匹配**:在量词后加 `?` 使其变为非贪婪匹配(如 `.*?`)
4. **使用合适的函数**:
- 只需检查是否存在匹配:`re.search()`
- 需要提取所有匹配:`re.findall()` 或 `re.finditer()`
- 需要替换内容:`re.sub()`
5. **考虑使用第三方库**:对于复杂需求,可使用 `regex` 模块(支持更多特性)
```python
# 性能比较示例
import timeit
# 未编译
def test_uncompiled():
return bool(re.search(r'\d{3}-\d{3}-\d{4}', "Phone: 123-456-7890"))
# 预编译
compiled_pattern = re.compile(r'\d{3}-\d{3}-\d{4}')
def test_compiled():
return bool(compiled_pattern.search("Phone: 123-456-7890"))
# 测试性能
print("未编译:", timeit.timeit(test_uncompiled, number=100000))
print("预编译:", timeit.timeit(test_compiled, number=100000))
# 输出示例(可能):
# 未编译: 0.15 seconds
# 预编译: 0.08 seconds
```
## 正则表达式调试工具
1. **在线正则表达式测试器**:
- [regex101.com](https://regex101.com/)
- [regexr.com](https://regexr.com/)
2. **Python内置调试**:
```python
pattern = re.compile(r'(\d{3})-(\d{3})-(\d{4})')
print(pattern.pattern) # 输出原始模式字符串
print(pattern.groups) # 输出分组数量
print(pattern.groupindex) # 输出命名分组映射
```
3. **使用 re.DEBUG 标志**:
```python
re.compile(r'(\d{3})-(\d{3})-(\d{4})', re.DEBUG)
# 输出:
# SUBPATTERN 1 0 0
# MAX_REPEAT 3 3
# IN
# CATEGORY CATEGORY_DIGIT
# LITERAL 45
# SUBPATTERN 2 0 0
# MAX_REPEAT 3 3
# IN
# CATEGORY CATEGORY_DIGIT
# LITERAL 45
# SUBPATTERN 3 0 0
# MAX_REPEAT 4 4
# IN
# CATEGORY CATEGORY_DIGIT
```