在Python编程中,正则表达式(Regular Expression,简称regex)是处理字符串的瑞士军刀。无论是数据清洗、日志分析,还是爬虫开发,正则表达式都能以简洁高效的方式解决复杂字符串匹配问题。本文通过20个真实场景案例,带你快速掌握正则表达式的核心用法。
一、基础验证场景
- 邮箱地址验证
import re
def validateemail(email):
pattern = r'^[a-zA-Z0-9.%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$'
return bool(re.match(pattern, email))
print(validate_email("test@example.com")) # True
print(validateemail("invalid.email")) # False
关键点:^和$确保从头到尾匹配,[a-zA-Z0-9.%+-]匹配用户名部分,.转义点号,{2,}要求顶级域名至少2个字符。
- 手机号码校验(中国大陆)
def validate_phone(phone):
pattern = r'^1[3-9]\d{9}$'
return bool(re.match(pattern, phone))
print(validate_phone("13800138000")) # True
print(validate_phone("12345678901")) # False
技巧:1[3-9]匹配运营商号段,\d{9}匹配剩余9位数字,总长度固定11位。
- 密码强度检测
def validate_password(password):
pattern = r'^(?=.[a-z])(?=.[A-Z])(?=.\d)(?=.[@$!%?&])[A-Za-z\d@$!%?&]{8,20}$'
return bool(re.match(pattern, password))
print(validate_password("StrongPass1!")) # True
print(validate_password("weakpass")) # False
原理:(?=...)是正向预查,确保同时包含大小写字母、数字和特殊字符,{8,20}限制长度。
二、数据提取场景
从文本提取所有数字
text = "订单号: 2023A001, 金额: ¥128.50"
numbers = re.findall(r'\d+.?\d*', text)
print(numbers) # ['2023', '001', '128.50']
扩展:若需提取整数,改用r'\b\d+\b';提取小数用r'\d+.\d+'。抓取网页URL
html = '链接
'
urls = re.findall(r'href="(https?://[^"]+)"', html)
print(urls) # ['https://example.com']
优化:添加re.IGNORECASE标志可匹配HTTP和HTTPS混合大小写情况。解析日志文件
log = "2023-10-01 12:00:00 ERROR: Disk full"
match = re.search(r'(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2}) (\w+): (.+)', log)
if match:
print(f"日期: {match.group(1)}, 时间: {match.group(2)}, 级别: {match.group(3)}, 内容: {match.group(4)}")
输出:
日期: 2023-10-01, 时间: 12:00:00, 级别: ERROR, 内容: Disk full
三、文本处理场景- 敏感词过滤
def censor_text(text, bad_words):
pattern = '|'.join(map(re.escape, bad_words))
return re.sub(pattern, '*', text)
text = "这个产品太糟糕了,服务态度极差"
print(censor_text(text, ["糟糕", "极差"])) # 这个产品太了,服务态度
注意:re.escape自动转义特殊字符,避免正则语法错误。
拆分复合分隔符
data = "苹果|香蕉,橙子;西瓜"
items = re.split(r'[|,;]', data)
print(items) # ['苹果', '香蕉', '橙子', '西瓜']
应用场景:处理CSV文件或用户自定义分隔符的数据。删除多余空格
text = " This is a messy sentence. "
cleaned = re.sub(r'\s+', ' ', text).strip()
print(cleaned) # "This is a messy sentence."
进阶:结合re.compile()预编译模式提升性能:
space_pattern = re.compile(r'\s+')
cleaned = space_pattern.sub(' ', text).strip()
四、高级匹配技巧
非贪婪匹配
html = "第一段
第二段
"
content = re.findall(r'(.?)
', html, re.DOTALL)
print(content) # ['第一段', '第二段']
对比:贪婪模式.会匹配整个字符串,非贪婪模式.*?在遇到第一个时停止。条件匹配(区分邮箱类型)
emails = ["edu@example.edu", "biz@example.biz"]
for email in emails:
match = re.search(r'(\w+@)(edu|biz).', email)
if match:print(f"{email} 是{match.group(2)}邮箱")输出:
edu@example.edu 是edu邮箱
biz@example.biz 是biz邮箱
- 提取重复字符
text = "1122334455"
repeats = re.findall(r'(\d)\1+', text)
print(repeats) # ['1', '2', '3', '4', '5']
原理:(\d)捕获数字,\1引用第一个分组,+匹配一次或多次重复。
五、实战案例集锦
- 身份证号校验(简易版)
def validate_id_card(id_card):
pattern = r'^[1-9]\d{5}(19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dX]$'
return bool(re.match(pattern, id_card))
print(validate_id_card("11010519991231003X")) # True
说明:该模式验证18位身份证号,包含地区码、出生日期和校验位。
提取中文段落
text = "Hello 你好,世界!This is a test."
chinese = re.findall(r'[\u4e00-\u9fa5]+', text)
print(chinese) # ['你好', '世界']
扩展:匹配中文标点:r'[\u4e00-\u9fa5,。、;:?!]'爬虫代理IP格式校验
def validate_proxy(proxy):
pattern = r'^\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}:\d{1,5}$'
return bool(re.match(pattern, proxy))
print(validate_proxy("192.168.1.1:8080")) # True
print(validate_proxy("256.300.1.1:99999")) # False
注意:实际IP范围需更严格校验,此处仅演示格式。
六、性能优化建议
date_pattern = re.compile(r'^\d{4}-\d{2}-\d{2}$')
date_pattern.match("2023-10-01")
只需判断是否存在匹配 → re.search()
需要所有匹配结果 → re.findall()
需要替换文本 → re.sub()
常见问题Q&A
Q2:如何匹配中文和英文混合字符串中的中文部分?
A:使用Unicode范围匹配:
text = "Python编程 Python Programming"
chinese = re.findall(r'[\u4e00-\u9fa5]+', text)
print(chinese) # ['编程']
Q3:正则表达式匹配效率低如何优化?
A:
避免嵌套量词(如(a+)+)
使用非贪婪模式替代贪婪模式
限制重复次数范围(如{3,6}优于*)
对固定字符串使用re.escape()转义后直接匹配
Q4:如何提取HTML标签间的文本?
A:非贪婪模式匹配:
html = "
内容
"texts = re.findall(r'>(.*?)</', html)
print(texts) # ['标题', '内容']
Q5:正则表达式能匹配二进制数据吗?
A:不能直接匹配,但可先解码为字符串(如UTF-8),或使用bytes类型正则(Python 3中需加b前缀):
binary_data = b'\x48\x65\x6c\x6c\x6f'
pattern = b'Hello'
match = re.search(pattern, binary_data)
通过掌握这些核心场景和优化技巧,你已具备解决80%以上字符串处理问题的能力。正则表达式的精髓在于"用简洁的语法描述复杂规则",建议通过实际项目不断练习,最终达到"看字符串即写正则"的境界。