Python 中正则表达式使用方法match、search、findall、finditer等常用方法介绍,及案例分析
1. 正则表达式基础
导入模块
python
import re
基本匹配方法
1.1. re.match() - 从字符串开头匹配
python
pattern = r"hello"
text = "hello world"
result = re.match(pattern, text)
if result:
print("匹配成功:", result.group()) # 输出: hello
else:
print("匹配失败")
1.2. re.search() - 搜索整个字符串
python
pattern = r"world"
text = "hello world"
result = re.search(pattern, text)
if result:
print("找到:", result.group()) # 输出: world
print("位置:", result.span()) # 输出: (6, 11)
1.3. re.findall() - 查找所有匹配
python
pattern = r"\d+" # 匹配一个或多个数字
text = "我有3个苹果和5个香蕉"
results = re.findall(pattern, text)
print(results) # 输出: ['3', '5']
1.4. re.finditer() - 返回迭代器
python
pattern = r"\w+"
text = "hello world python"
for match in re.finditer(pattern, text):
print(f"找到: '{match.group()}' 位置: {match.span()}")
1.5. re.sub() - 替换匹配内容
python
pattern = r"苹果"
text = "我喜欢吃苹果"
new_text = re.sub(pattern, "香蕉", text)
print(new_text) # 输出: 我喜欢吃香蕉
1.6. re.split() - 根据模式分割字符串
python
pattern = r"\s+" # 一个或多个空白字符
text = "hello world python"
parts = re.split(pattern, text)
print(parts) # 输出: ['hello', 'world', 'python']
2. 正则表达式语法详解
常用元字符
python
# 字符类
text = "abc123 def"
print(re.findall(r"[a-z]", text)) # 所有小写字母: ['a', 'b', 'c', 'd', 'e', 'f']
print(re.findall(r"[0-9]", text)) # 所有数字: ['1', '2', '3']
print(re.findall(r"[^0-9]", text)) # 非数字: ['a', 'b', 'c', ' ', 'd', 'e', 'f']
# 预定义字符类
print(re.findall(r"\d", text)) # 数字: ['1', '2', '3']
print(re.findall(r"\D", text)) # 非数字: ['a', 'b', 'c', ' ', 'd', 'e', 'f']
print(re.findall(r"\w", text)) # 单词字符: ['a', 'b', 'c', '1', '2', '3', 'd', 'e', 'f']
print(re.findall(r"\W", text)) # 非单词字符: [' ']
print(re.findall(r"\s", text)) # 空白字符: [' ']
量词
python
text = "a ab abb abbb abbbb"
print(re.findall(r"ab?", text)) # a后跟0或1个b: ['a', 'ab', 'ab', 'ab', 'ab']
print(re.findall(r"ab+", text)) # a后跟1个或多个b: ['ab', 'abb', 'abbb', 'abbbb']
print(re.findall(r"ab*", text)) # a后跟0个或多个b: ['a', 'ab', 'abb', 'abbb', 'abbbb']
print(re.findall(r"ab{2}", text)) # a后跟2个b: ['abb']
print(re.findall(r"ab{2,3}", text)) # a后跟2-3个b: ['abb', 'abbb']
位置锚点
python
text = "hello world"
print(re.search(r"^hello", text)) # 匹配开头
print(re.search(r"world$", text)) # 匹配结尾
print(re.search(r"\bworld\b", text)) # 单词边界
分组
python
text = "2023-12-25"
# 捕获分组
match = re.search(r"(\d{4})-(\d{2})-(\d{2})", text)
if match:
print("完整匹配:", match.group(0)) # 2023-12-25
print("年:", match.group(1)) # 2023
print("月:", match.group(2)) # 12
print("日:", match.group(3)) # 25
print("所有分组:", match.groups()) # ('2023', '12', '25')
# 非捕获分组 (?:...)
match = re.search(r"(?:\d{4})-(\d{2})-(\d{2})", text)
print(match.groups()) # 只有月和日: ('12', '25')
3. 实用案例
3.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))
emails = ["test@example.com", "invalid.email", "name@domain.co.uk"]
for email in emails:
print(f"{email}: {'有效' if validate_email(email) else '无效'}")
3.2: 提取手机号码
python
def extract_phones(text):
# 匹配11位手机号
pattern = r'1[3-9]\d{9}'
return re.findall(pattern, text)
text = "联系电话: 13812345678, 13987654321,其他号码: 15011112222"
phones = extract_phones(text)
print("找到的手机号:", phones)
3.3: HTML标签处理
python
def remove_html_tags(html):
# 移除HTML标签
pattern = r'<[^>]+>'
return re.sub(pattern, '', html)
html = "<div><p>这是一个段落</p><br></div>"
clean_text = remove_html_tags(html)
print("清理后:", clean_text)
3.4: 密码强度验证
python
def check_password_strength(password):
if len(password) < 8:
return "弱: 密码长度至少8位"
checks = [
(r'[A-Z]', "大写字母"),
(r'[a-z]', "小写字母"),
(r'[0-9]', "数字"),
(r'[^A-Za-z0-9]', "特殊字符")
]
strength = 0
missing = []
for pattern, desc in checks:
if re.search(pattern, password):
strength += 1
else:
missing.append(desc)
if strength == 4:
return "强"
elif strength == 3:
return f"中 - 缺少: {', '.join(missing)}"
else:
return f"弱 - 缺少: {', '.join(missing)}"
passwords = ["abc", "abcdefgh", "Abc123!", "StrongPass123!"]
for pwd in passwords:
print(f"'{pwd}': {check_password_strength(pwd)}")
3.5: 数据清洗
python
def clean_data(text):
# 移除多余空格
text = re.sub(r'\s+', ' ', text)
# 移除特殊字符,只保留中文、英文、数字和常见标点
text = re.sub(r'[^\u4e00-\u9fa5a-zA-Z0-9\s.,!?;:]', '', text)
return text.strip()
dirty_text = " 这是一段 需要清理的文本!!包含@#特殊字符... "
clean_text = clean_data(dirty_text)
print(f"清理前: '{dirty_text}'")
print(f"清理后: '{clean_text}'")
4. 高级技巧与注意事项
编译正则表达式(提高性能)
python
# 对于需要多次使用的模式,先编译
pattern = re.compile(r'\d{3}-\d{3}-\d{4}') # 电话号码模式
texts = ["电话: 123-456-7890", "另一个: 111-222-3333"]
for text in texts:
match = pattern.search(text)
if match:
print("找到电话:", match.group())
使用原始字符串
python
# 推荐使用原始字符串,避免转义问题
good_pattern = r"\d+\\.\d+" # 匹配数字.数字
bad_pattern = "\d+\\.\d+" # 不推荐,需要双重转义
贪婪 vs 非贪婪匹配
python
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>']
使用标志位
python
text = "Hello\nWORLD\nPython"
# 忽略大小写
print(re.findall(r'hello', text, re.IGNORECASE)) # ['Hello']
# 多行模式
print(re.findall(r'^[A-Z]+', text, re.MULTILINE)) # ['H', 'WORLD', 'P']
# 点号匹配所有字符(包括换行符)
print(re.findall(r'.+', text, re.DOTALL)) # ['Hello\nWORLD\nPython']
5. 常见错误与调试技巧
常见错误
python
# 1. 忘记转义特殊字符
text = "1.5"
# wrong = re.findall(r"1.5", text) # 会匹配 1任意字符5
correct = re.findall(r"1\.5", text) # 正确转义
# 2. 过度复杂的正则表达式
# 尽量保持简单,复杂的匹配可以分步进行
# 3. 性能问题
# 避免使用嵌套量词和过于宽泛的匹配
调试技巧
python
def debug_regex(pattern, text):
print(f"模式: {pattern}")
print(f"文本: {text}")
try:
matches = list(re.finditer(pattern, text))
if matches:
for i, match in enumerate(matches):
print(f"匹配 {i+1}: '{match.group()}' 位置: {match.span()}")
if match.groups():
print(f" 分组: {match.groups()}")
else:
print("没有找到匹配")
except re.error as e:
print(f"正则表达式错误: {e}")
# 调试示例
debug_regex(r'(\d+)-([a-z]+)', "123-abc 456-def")
6. 最佳实践总结
- 使用原始字符串 :总是使用
r"pattern"格式 - 编译常用模式:重复使用的正则表达式应该编译
- 保持简单:复杂的匹配可以分解为多个简单的正则表达式
- 测试充分:使用各种边界情况进行测试
- 考虑性能:避免回溯灾难,使用非贪婪匹配适当
- 添加注释:复杂的正则表达式要添加注释说明
python
# 好的实践示例
import re
# 编译常用模式
EMAIL_PATTERN = re.compile(
r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
)
def validate_emails(emails):
"""验证邮箱列表"""
valid_emails = []
for email in emails:
if EMAIL_PATTERN.match(email):
valid_emails.append(email)
return valid_emails
# 使用示例
emails = ["user@example.com", "invalid", "test@domain.org"]
print("有效邮箱:", validate_emails(emails))
掌握这些正则表达式技巧将极大提高你在Python中处理文本数据的能力!