1. 初识re.sub()Python正则替换的瑞士军刀第一次接触re.sub()是在处理一堆杂乱无章的日志文件时。当时需要从几百MB的服务器日志中提取关键错误信息手动查找简直是大海捞针。直到发现这个神奇的函数我才真正体会到正则表达式的威力。re.sub()就像文本处理中的多功能瑞士军刀不仅能找到特定模式的文本还能按照你的需求进行精准替换。先来看个最简单的例子把字符串中的所有数字替换成星号。这个操作在数据脱敏时特别有用比如隐藏用户手机号的部分数字import re text 用户手机号13812345678订单号ORD202112345 result re.sub(r\d, *, text) print(result) # 输出用户手机号***********订单号ORD*********这个例子中\d匹配任意数字*是替换内容。短短一行代码就完成了看似复杂的任务。我特别喜欢re.sub()的这种直接了当——告诉它找什么和换成什么它就能完美执行。2. 参数详解掌握re.sub()的五大核心要素2.1 pattern正则表达式的艺术pattern参数是re.sub()的灵魂所在。经过多年实践我总结了几种最常用的匹配模式\d匹配任意数字等价于[0-9]\w匹配字母、数字和下划线\s匹配空白字符空格、制表符等.匹配除换行符外的任意字符[a-z]匹配指定范围内的字符特殊技巧使用^表示否定比如[^0-9]匹配所有非数字字符。这在清理特殊字符时特别管用text 价格$19.99 折扣20% clean_text re.sub(r[^0-9.], , text) print(clean_text) # 输出19.99202.2 repl不只是简单替换repl参数远比看起来强大。它可以是字符串也可以是函数。当需要动态生成替换内容时函数形式就派上用场了def to_upper(match): return match.group().upper() text make this title case result re.sub(r\b\w, to_upper, text) print(result) # 输出Make This Title Case2.3 count精准控制替换范围count参数经常被忽视但它能在大型文本处理中显著提升性能。比如只替换前3个匹配项text a a a a a a a result re.sub(ra, b, text, count3) print(result) # 输出b b b a a a a3. 实战演练从简单到复杂的替换场景3.1 数据清洗让杂乱文本焕然一新上周处理用户提交的表单数据时遇到了各种格式混乱的电话号码。有的带区号有的带国际码还有的夹杂各种分隔符。用re.sub()统一格式简直不要太爽phones [ 1 (650) 123-4567, 650.123.4567, 650 123 4567, (650)1234567 ] for phone in phones: standardized re.sub(r[^\d], , phone) print(standardized) # 统一输出165012345673.2 日志处理快速提取关键信息服务器日志通常包含大量冗余信息。用re.sub()可以快速提取关键错误log 2023-05-01 12:00:00 [INFO] User login 2023-05-01 12:01:00 [ERROR] Database connection failed 2023-05-01 12:02:00 [WARNING] High memory usage # 提取所有ERROR级别的日志 errors re.sub(r^(?!.*\[ERROR\]).*$, , log, flagsre.MULTILINE) print(errors.strip())3.3 模板渲染动态内容生成最近用re.sub()实现了一个简单的模板引擎处理包含变量的文本template Hello {name}, your order {order_id} is ready! context {name: John, order_id: 12345} def render(match): key match.group(1) return str(context.get(key, )) result re.sub(r\{(.*?)\}, render, template) print(result) # 输出Hello John, your order 12345 is ready!4. 高级技巧提升正则替换的威力4.1 反向引用重用匹配内容在改写日期格式时反向引用特别有用。比如把MM/DD/YYYY改成YYYY-MM-DDdate 12/31/2022 new_date re.sub(r(\d{2})/(\d{2})/(\d{4}), r\3-\1-\2, date) print(new_date) # 输出2022-12-314.2 条件替换更灵活的内容处理当替换逻辑比较复杂时可以使用函数作为repl参数。比如实现一个简单的Markdown转HTMLdef md_to_html(match): text match.group(2) if match.group(1) *: return fem{text}/em elif match.group(1) **: return fstrong{text}/strong markdown 这是*斜体*这是**粗体** html re.sub(r(\*)(.*?)\1, md_to_html, markdown) print(html) # 输出这是em斜体/em这是strong粗体/strong4.3 性能优化编译正则表达式处理大量文本时预编译正则表达式能显著提升性能pattern re.compile(r\d{3}-\d{2}-\d{4}) # 美国社保号格式 texts [SSN: 123-45-6789, No SSN here, Another: 987-65-4321] for text in texts: redacted pattern.sub(XXX-XX-XXXX, text) print(redacted)5. 避坑指南常见问题与解决方案5.1 贪婪匹配 vs 非贪婪匹配新手常被贪婪匹配坑到。比如想提取HTML标签中的内容html div内容1/divdiv内容2/div # 错误做法贪婪匹配 wrong re.sub(rdiv(.*)/div, r\1, html) print(wrong) # 输出内容1/divdiv内容2 # 正确做法非贪婪匹配 correct re.sub(rdiv(.*?)/div, r\1, html) print(correct) # 输出内容1内容25.2 多行匹配的正确姿势处理多行文本时记得使用re.MULTILINE标志text 第一行 第二行 第三行 # 不加MULTILINE标志 result1 re.sub(r^.*$, X, text) print(result1) # 替换整个文本为X # 加上MULTILINE标志 result2 re.sub(r^.*$, X, text, flagsre.MULTILINE) print(result2) # 每行替换为X5.3 Unicode字符处理处理多语言文本时记得使用re.UNICODE标志text 中文Chinese にほんご한국어 # 匹配所有字母包括非ASCII letters re.sub(r[^\w\s], , text, flagsre.UNICODE) print(letters) # 输出中文Chinese にほんご한국어6. 综合案例从零构建一个文本处理工具让我们把这些知识综合起来构建一个实用的文本清理工具import re def clean_text(text): # 移除多余空格 text re.sub(r\s, , text) # 标准化标点 text re.sub(r([,.!?])(\w), r\1 \2, text) # 移除特殊字符保留字母、数字、常用标点和空格 text re.sub(r[^\w\s,.!?], , text, flagsre.UNICODE) # 修正常见拼写错误 text re.sub(r\bteh\b, the, text, flagsre.IGNORECASE) return text.strip() dirty_text This is teh example text,with weird spacing...and special!characters? print(clean_text(dirty_text)) # 输出This is the example text, with weird spacing... and special! characters?这个工具虽然简单但已经能处理日常遇到的大部分文本清理需求。根据实际需要你可以继续添加更多规则比如处理URL、邮箱地址、电话号码等。