Python正则表达式匹配和替换详细指南

正则表达式是处理文本的强大工具,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']

最佳实践

  1. 使用原始字符串r"pattern" 避免转义问题
  2. 编译常用模式:提高性能
  3. 合理使用分组:使代码更清晰
  4. 处理异常情况:确保匹配失败时不会崩溃
  5. 测试正则表达式:使用在线工具验证模式

总结

正则表达式是Python中处理文本的强大工具,re.sub()函数特别适用于字符串替换任务。通过掌握基本语法和高级技巧,你可以高效地处理各种文本处理需求,从简单的字符串替换到复杂的数据提取和格式化。

记住:正则表达式虽然强大,但也要适度使用,对于简单的字符串操作,Python内置的字符串方法可能更合适。

相关推荐
怒码ing3 小时前
List<?>和List<Object>区别
windows·python·list
那雨倾城3 小时前
PiscCode轨迹跟踪Mediapipe + OpenCV进阶:速度估算
图像处理·人工智能·python·opencv·计算机视觉
2501_920047034 小时前
bash自带的切片操作
开发语言·python·bash
偷心伊普西隆4 小时前
Python EXCEL 小技巧:最快重新排列dataframe函数
python·excel
我是海飞4 小时前
Tensorflow Lite 的yes/no语音识别音频预处理模型训练教程
python·学习·tensorflow·音视频·嵌入式·语音识别
know__ledge4 小时前
Python学习3.0使用Unittest框架运行测试用例
python·学习·测试用例
绝无仅有4 小时前
从拉取代码到前端运行访问:Vue 前端项目的常规启动流程
后端·面试·github
青鱼入云5 小时前
java面试中经常会问到的zookeeper问题有哪些(基础版)
java·面试·java-zookeeper
鲸落落丶5 小时前
finalize() 方法介绍
开发语言·python