正则表达式是处理文本的强大工具,Python通过re
模块提供了完整的正则表达式功能。本文将详细介绍Python中的正则匹配和替换操作。
基础语法
导入re模块
arduino
import re
基本元字符
.
- 匹配任意字符(除了换行符)\d
- 匹配数字\w
- 匹配字母、数字、下划线\s
- 匹配空白字符[]
- 字符集*
- 0次或多次+
- 1次或多次?
- 0次或1次{n}
- 恰好n次{n,}
- 至少n次{n,m}
- n到m次
常用匹配方法
1. re.match() - 从字符串开头匹配
python
text = "Hello World 2024"
result = re.match(r"Hello", text)
if result:
print("匹配成功:", result.group()) # 输出: Hello
2. re.search() - 搜索整个字符串
python
text = "The year is 2024"
result = re.search(r"\d{4}", text)
if result:
print("找到数字:", result.group()) # 输出: 2024
3. re.findall() - 查找所有匹配项
python
text = "苹果10元, 香蕉5元, 橙子8元"
prices = re.findall(r"\d+元", text)
print(prices) # 输出: ['10元', '5元', '8元']
4. re.finditer() - 返回迭代器
python
text = "联系: 123-4567, 987-6543"
for match in re.finditer(r"\d{3}-\d{4}", text):
print(f"找到电话: {match.group()} 位置: {match.span()}")
替换方法详解
re.sub() 基本用法
python
text = "今天是2023年12月15日"
# 将年份替换为2024
new_text = re.sub(r"2023", "2024", text)
print(new_text) # 输出: 今天是2024年12月15日
使用分组和引用
python
text = "张三 李四 王五"
# 交换姓和名的位置
new_text = re.sub(r"(\w+) (\w+)", r"\2 \1", text)
print(new_text) # 输出: 李四 张三 王五
使用函数进行复杂替换
python
def double_number(match):
number = int(match.group())
return str(number * 2)
text = "数字: 5, 10, 15"
new_text = re.sub(r"\d+", double_number, text)
print(new_text) # 输出: 数字: 10, 20, 30
实际应用案例
案例1:格式化电话号码
python
def format_phone_number(text):
# 将各种格式的电话号码统一为: (xxx) xxx-xxxx
pattern = r"(\d{3})[-.\s]?(\d{3})[-.\s]?(\d{4})"
replacement = r"(\1) \2-\3"
return re.sub(pattern, replacement, text)
phone_text = "联系: 123-456-7890, 123.456.7890, 123 456 7890"
formatted = format_phone_number(phone_text)
print(formatted)
# 输出: 联系: (123) 456-7890, (123) 456-7890, (123) 456-7890
案例2:清理HTML标签
python
def remove_html_tags(text):
# 移除HTML标签,保留文本内容
return re.sub(r"<[^>]+>", "", text)
html_text = "<h1>标题</h1><p>这是一个<strong>段落</strong></p>"
clean_text = remove_html_tags(html_text)
print(clean_text) # 输出: 标题这是一个段落
案例3:数据脱敏
python
def mask_sensitive_data(text):
# 隐藏身份证号中间部分
text = re.sub(r"(\d{4})\d{8}(\d{4})", r"\1********\2", text)
# 隐藏手机号中间部分
text = re.sub(r"(\d{3})\d{4}(\d{4})", r"\1****\2", text)
return text
sensitive_text = "身份证: 510123199001011234, 手机: 13800138000"
masked_text = mask_sensitive_data(sensitive_text)
print(masked_text)
# 输出: 身份证: 5101********1234, 手机: 138****8000
案例4:Salesforce Flow版本更新
python
import re
def update_flow_version(rows, flow_name, old_version, new_version):
"""
更新Salesforce Flow的多语言键名版本号
"""
updated_rows = []
for row in rows:
if row and len(row) >= 1:
key = row[0]
if key and isinstance(key, str):
patterns = [
(f"Flow\.Flow\.{flow_name}\.{old_version}\.",
f"Flow.Flow.{flow_name}.{new_version}."),
(f"Flow\.AutoLaunchedFlow\.{flow_name}\.{old_version}\.",
f"Flow.AutoLaunchedFlow.{flow_name}.{new_version}."),
]
new_key = key
for pattern, replacement in patterns:
if re.search(pattern, key):
new_key = re.sub(pattern, replacement, key)
break
# 更新行的第一个元素
updated_row = list(row)
updated_row[0] = new_key
updated_rows.append(updated_row)
else:
updated_rows.append(row)
else:
updated_rows.append(row)
return updated_rows
# 使用示例
rows = [
["Flow.Flow.CustomerOnboarding.1.title", "客户入驻流程"],
["Flow.AutoLaunchedFlow.CustomerOnboarding.1.description", "自动启动流程"],
["Other.Key", "其他值"]
]
updated = update_flow_version(rows, "CustomerOnboarding", "1", "2")
for row in updated:
print(row)
# 输出:
# ['Flow.Flow.CustomerOnboarding.2.title', '客户入驻流程']
# ['Flow.AutoLaunchedFlow.CustomerOnboarding.2.description', '自动启动流程']
# ['Other.Key', '其他值']
案例5:日志文件处理
python
def parse_log_file(log_content):
"""
解析日志文件,提取时间戳、级别和消息
"""
log_pattern = r"(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) [(\w+)] (.+)"
logs = []
for line in log_content.split('\n'):
match = re.match(log_pattern, line)
if match:
timestamp, level, message = match.groups()
logs.append({
'timestamp': timestamp,
'level': level,
'message': message
})
return logs
# 示例日志内容
log_content = """2024-01-15 10:30:25 [INFO] 用户登录成功
2024-01-15 10:31:10 [ERROR] 数据库连接失败
2024-01-15 10:32:45 [WARNING] 内存使用率过高"""
parsed_logs = parse_log_file(log_content)
for log in parsed_logs:
print(f"{log['timestamp']} - {log['level']}: {log['message']}")
高级技巧
1. 编译正则表达式(提高性能)
python
# 对于需要多次使用的模式,先编译
phone_pattern = re.compile(r"(\d{3})-(\d{3})-(\d{4})")
texts = ["123-456-7890", "987-654-3210"]
for text in texts:
match = phone_pattern.search(text)
if match:
print(f"完整匹配: {match.group()}, 分组: {match.groups()}")
2. 使用命名分组
python
text = "日期: 2024-01-15"
pattern = r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})"
match = re.search(pattern, text)
if match:
print(f"年: {match.group('year')}, 月: {match.group('month')}, 日: {match.group('day')}")
3. 非贪婪匹配
python
text = "<div>内容1</div><div>内容2</div>"
# 贪婪匹配
greedy = re.findall(r"<div>(.*)</div>", text)
print("贪婪匹配:", greedy) # 输出: ['内容1</div><div>内容2']
# 非贪婪匹配
non_greedy = re.findall(r"<div>(.*?)</div>", text)
print("非贪婪匹配:", non_greedy) # 输出: ['内容1', '内容2']
4. 前后查找
python
text = "价格: $100, 折扣: $20"
# 查找$后面的数字
prices = re.findall(r"(?<=$)\d+", text)
print("价格:", prices) # 输出: ['100', '20']
最佳实践
- 使用原始字符串 :
r"pattern"
避免转义问题 - 编译常用模式:提高性能
- 合理使用分组:使代码更清晰
- 处理异常情况:确保匹配失败时不会崩溃
- 测试正则表达式:使用在线工具验证模式
总结
正则表达式是Python中处理文本的强大工具,re.sub()
函数特别适用于字符串替换任务。通过掌握基本语法和高级技巧,你可以高效地处理各种文本处理需求,从简单的字符串替换到复杂的数据提取和格式化。
记住:正则表达式虽然强大,但也要适度使用,对于简单的字符串操作,Python内置的字符串方法可能更合适。