Python re.sub()优化:多替换操作能否合并为单一操作?
简化Python正则处理姓名格式的方案
咱们先来明确下需求:你手里有个Python列表,里面的字符串是以下四种格式之一(名称会变化):
Mr: Smith
Mr: Smith; John
Smith
Smith; John
想要把它们统一转换成这种格式:
Mr,Smith,fname
Mr,Smith,John
title,Smith,fname
title,Smith,John
原来你用了四次re.sub()操作实现了需求,但想提升效率换成单一操作——当然可以!咱们可以利用正则的分组捕获+动态替换函数来搞定,一次匹配就能覆盖所有情况。
优化思路
核心是写一个能同时匹配四种格式的正则表达式,把标题、姓氏、名字分别捕获到不同分组里,然后通过替换函数根据捕获到的内容动态生成目标字符串,不用多次调用re.sub()。
完整代码示例
先修正你原来代码里的小问题(比如正则没加引号、循环里错误修改列表的问题),然后给出优化后的代码:
import re with open("path/to/file", 'r') as fileset: dataset = [item.strip() for item in fileset.readlines()] # 先统一去除空白和换行 def format_name(match): # 提取捕获的分组:标题、姓氏、名字 title = match.group(1) or 'title' last_name = match.group(2) first_name = match.group(3) or 'fname' return f"{title},{last_name},{first_name}" # 匹配所有四种格式的正则 pattern = r'^(?:(\w+):\s*)?(\w+)(?:;\s*(\w+))?$' formatted_dataset = [re.sub(pattern, format_name, item) for item in dataset]
正则表达式说明
咱们拆解下这个正则^(?:(\w+):\s*)?(\w+)(?:;\s*(\w+))?$:
^(?:(\w+):\s*)?:可选的标题部分,(\w+)捕获标题(比如Mr),:\s*匹配冒号和后面的任意空白,整个用非捕获组(?:...)包裹并加?表示可选(\w+):必选的姓氏部分,直接捕获姓氏(比如Smith)(?:;\s*(\w+))?$:可选的名字部分,;\s*匹配分号和后面的任意空白,(\w+)捕获名字(比如John),同样用非捕获组包裹并加?表示可选^和$确保匹配整行内容,避免部分匹配的问题
替换函数说明
format_name函数接收正则匹配对象,然后:
- 如果捕获到了标题(
match.group(1)不为空)就用它,否则用title - 姓氏是必捕获的,直接取
match.group(2) - 如果捕获到了名字(
match.group(3)不为空)就用它,否则用fname - 最后用f-string拼接成目标格式的字符串
这样一来,只需要一次正则替换操作就能处理所有四种情况,代码更简洁,效率也更高~
内容的提问来源于stack exchange,提问作者t.r.orion
相关产品推荐
相关产品推荐

