Python 正则表达式的re.sub()方法详解
Python 正则表达式的re.sub()方法是用于替换字符串中匹配正则模式的子串的核心工具,其核心逻辑是:根据正则表达式匹配目标字符串中的子串,并用指定内容(字符串或函数返回值)替换这些子串。以下从功能、参数、高级用法、常见场景等维度详细解析。
一、基础语法与核心参数
re.sub()的标准语法为:
re.sub(pattern, repl, string, count=0, flags=0)
参数说明:
- pattern:正则表达式模式(必选),用于匹配需要替换的子串;
- repl:替换内容(必选),可以是字符串或函数(动态生成替换内容);
- string:待处理的原始字符串(必选);
- count:最多替换次数(可选),默认0表示替换所有匹配项;
- flags:正则表达式标志(可选),如re.IGNORECASE(忽略大小写)、re.DOTALL(.匹配换行)等。
返回值:替换后的新字符串(原字符串不会被修改)。
二、repl为字符串的替换逻辑
当repl是字符串时,支持通过反向引用提取匹配的子组(Group),并将其插入到替换结果中。
1. 基础替换(无反向引用)
直接用固定字符串替换所有匹配项。
示例:将字符串中的所有空格替换为下划线:
import re
text = "hello world python"
result = re.sub(r' ', '_', text) # 替换所有空格
print(result) # 输出:hello_world__python
2. 反向引用(引用匹配的子组)
若正则表达式中定义了捕获组(用()包裹的子模式),可以通过\n(n为组号)或\g<name>(命名组)引用这些组的内容到替换字符串中。
示例 1:调整日期格式
将YYYY-MM-DD格式的日期替换为YYYY/MM/DD:
text = "今天是2023-10-05,明天是2023-10-06"
# 正则匹配日期(分组:年、月、日)
pattern = r'(\d{4})-(\d{2})-(\d{2})'
# 替换为:年/月/日(通过 \1、\2、\3 引用分组)
result = re.sub(pattern, r'\1/\2/\3', text)
print(result) # 输出:今天是2023/10/05,明天是2023/10/06
示例 2:命名组提高可读性
使用命名组(?P<year>\d{4})替代数字组号:
pattern = r'(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})'
result = re.sub(pattern, r'\g<year>/\g<month>/\g<day>', text)
print(result) # 输出同上
3. 特殊字符转义
若替换字符串中需要包含反斜杠\或$(在部分正则实现中为特殊字符),需使用原始字符串或转义符\。
示例:将路径中的\替换为/(注意原始字符串的使用):
path = r'C:\Program Files\Python'
result = re.sub(r'\\', '/', path) # 正则中用 \\ 匹配实际的 \
print(result) # 输出:C:/Program Files/Python
三、repl为函数的动态替换
当替换逻辑需要根据匹配内容动态计算时(如数值转换、条件判断),可以将repl指定为一个函数。该函数接收一个匹配对象(re.Match)作为参数,返回替换后的字符串。
核心逻辑
1. 正则表达式匹配到子串后,生成对应的Match对象;
2. 调用repl函数,传入该Match对象;
3. 函数返回的字符串将作为替换结果。
示例 1:将数字替换为平方值
将字符串中的每个整数替换为其平方:
import re
def square_match(match):
num = int(match.group()) # 获取匹配的数字字符串,转为整数
return str(num ** 2) # 返回平方后的字符串
text = "a=3, b=5, c=7"
result = re.sub(r'\d+', square_match, text)
print(result) # 输出:a=9, b=25, c=49
示例 2:首字母大写(条件替换)
将每个单词的首字母大写,其余字母小写(忽略缩写如HTTP):
def capitalize_word(match):
word = match.group()
# 如果单词全大写(如 HTTP),保持原样;否则首字母大写
if word.isupper():
return word
return word[0].upper() + word[1:].lower()
text = "hello world! HTTP is awesome"
result = re.sub(r'\b\w+\b', capitalize_word, text)
print(result) # 输出:Hello World! HTTP Is Awesome
四、count参数:限制替换次数
count用于指定最多替换的匹配项数量(从左到右匹配的前count个)。若count=0(默认),则替换所有匹配项。
示例:只替换前两个空格为下划线:
text = "a b c d e"
result = re.sub(r' ', '_', text, count=2) # 替换前2个空格
print(result) # 输出:a_b_c d e
五、flags参数:正则匹配模式
通过flags可以修改正则表达式的匹配规则(如忽略大小写、多行匹配等)。常见标志如下:
|
标志 |
说明 |
|
re.IGNORECASE |
匹配时忽略大小写(如[A-Z]匹配任意大小写字母) |
|
re.DOTALL |
让.匹配包括换行符\n在内的所有字符 |
|
re.MULTILINE |
多行模式,^和$匹配行首/行尾(而非全文) |
|
re.VERBOSE |
允许正则表达式分行编写,添加注释(提高可读性) |
示例:忽略大小写替换
将字符串中的python替换为Python(不区分大小写):
text = "I love Python, PYTHON is cool"
result = re.sub(r'python', 'Python', text, flags=re.IGNORECASE)
print(result) # 输出:I love Python, Python is cool
六、re.subn():返回替换次数
re.subn()是re.sub()的变体,返回一个元组(新字符串, 替换次数),适用于需要统计替换次数的场景。
示例:统计替换次数:
text = "apple, apple, banana, apple"
new_text, count = re.subn(r'apple', 'orange', text)
print(new_text) # 输出:orange, orange, banana, orange
print(count) # 输出:3(替换了3次)
七、常见应用场景
1. 数据清洗(格式化字符串)
- 场景:调整日期、时间、电话号码等格式;
- 示例:将2023/10/05格式的日期统一为2023-10-05:text = "日期:2023/10/05,另一个日期:2023/11/20"
result = re.sub(r'(\d{4})/(\d{2})/(\d{2})', r'\1-\2-\3', text)
print(result) # 输出:日期:2023-10-05,另一个日期:2023-11-20
2. 敏感信息脱敏(隐藏部分字符)
- 场景:隐藏手机号、身份证号的部分数字;
- 示例:将手机号中间4位替换为****:text = "联系电话:13812345678,备用电话:13987654321"
result = re.sub(r'(\d{3})\d{4}(\d{4})', r'\1****\2', text)
print(result) # 输出:联系电话:138****5678,备用电话:139****4321
3. 文本预处理(去除冗余内容)
- 场景:删除多余空格、清理HTML标签;
- 示例:删除字符串中的多个连续空格(保留单个空格):text = "hello world python"
result = re.sub(r' +', ' ', text) # 用单个空格替换多个空格
print(result) # 输出:hello world python
八、注意事项
1. 正则表达式的贪婪匹配:
正则默认是贪婪匹配(尽可能匹配更长的子串),可能导致替换范围超出预期。若需非贪婪匹配,需在量词后加?(如r'<.*?>'匹配最短的 HTML 标签)。
2. 反向引用的组号有效性:
若正则中未定义对应组号(如使用\3但正则只有2个组),会抛出re.error异常。
3. 函数替换的性能:
当需要大量替换时,函数替换(repl为函数)的性能可能低于字符串替换,需根据场景选择。
总结
re.sub()是 Python 正则表达式中最灵活的替换工具,支持固定字符串替换、动态函数替换,可通过反向引用和标志参数实现复杂的文本处理逻辑。其核心优势在于精准匹配+灵活替换,广泛应用于数据清洗、文本预处理、日志分析等场景。掌握re.sub()的用法,能显著提升文本处理的效率和代码的健壮性。
浙公网安备 33010602011771号