编程学习网 > 编程语言 > Python > Python 的 re 模块中 split()、sub()、subn() 方法有什么作用?
2026
06-13

Python 的 re 模块中 split()、sub()、subn() 方法有什么作用?


一行日志拆错,后面的字段全歪了。

原始数据长这样:

2026-06-04 10:21:33 | order_id=77881, user_id=1024; status=PAID   amount=199

有人直接写:

line.split(" ")

我看到这种写法一般会皱一下眉。空格数量一变,字段位置就乱;分隔符从逗号换成分号,又要补一坨判断。Python 里处理这种脏字符串,re 模块里的 split()sub()subn() 反而更像干活用的刀。

先看 re.split()

它不是按固定字符切,而是按正则规则切。日志、导入文件、运营后台导出的 CSV,最常见的问题就是分隔符不老实:有时一个空格,有时多个空格,有时逗号、分号、竖线混着来。

import re
line = "order_id=77881, user_id=1024; status=PAID   amount=199"
parts = re.split(r"[,;\s]+", line)
print(parts)
# ['order_id=77881', 'user_id=1024', 'status=PAID', 'amount=199']

这里的 [,;\s]+ 我平时会这么写,意思是:逗号、分号、空白字符,都算分隔符,而且连续出现也只切一次。

这比一层层 replace()  split() 干净多了。

有个细节要注意,如果正则里用了捕获括号,分隔符也会被保留下来。这个坑我见过几次,排查半天发现是括号多写了。

text = "A, B; C"
print(re.split(r"[,;]\s*", text))
# ['A', 'B', 'C']
print(re.split(r"([,;])\s*", text))
# ['A', ',', 'B', ';', 'C']

如果你不是故意要保留分隔符,就别随手加括号。真要分组但不想保留,用 (?:...)

print(re.split(r"(?:[,;])\s*", text))
# ['A', 'B', 'C']

再看 re.sub()

这个更常用,替换。不是简单字符串替换,而是按模式替换。

比如接口日志里手机号要脱敏,别写一堆切片,字段格式一变就崩。直接按手机号规则处理。

import re
log = "buyer=13812345678 receiver=13988887777 order=77881"
safe_log = re.sub(
    r"(?<!\d)(1[3-9]\d)\d{4}(\d{4})(?!\d)",
    r"\1****\2",
    log
)
print(safe_log)
# buyer=138****5678 receiver=139****7777 order=77881

这段正则看着长一点,但它做了两件事:只处理 11 位手机号;前后不能再跟数字,避免把一串订单号中间误伤。

re.sub() 的第三个参数是替换后的内容。这个内容可以是字符串,也可以是函数。函数替换在清洗数据时特别顺手。

比如运营导入金额,有人填 1,299.00,有人填  299 ,还有人复制了全角空格。入库前先清一下:

import re
from decimal import Decimal
raw_amounts = ["1,299.00", " 299 ", "39."]

def normalize_amount(value: str) -> Decimal:
    value = value.translate(str.maketrans("0123456789.", "0123456789."))
    value = re.sub(r"[^\d.]", "", value)
    if not value:
        raise ValueError("金额为空,不能入库")
    return Decimal(value)

for item in raw_amounts:
    print(normalize_amount(item))

这里我没有上来就写复杂正则。先把全角数字转半角,再把非数字和小数点干掉。代码是给以后排问题的人看的,不是给正则比赛看的。

sub() 还有一个 count 参数,能限制替换次数。

这个在处理日志头的时候挺有用,比如只去掉第一段时间,不动后面的业务内容。

import re
line = "2026-06-04 10:21:33 ERROR create_time=2026-06-01 msg=failed"
clean = re.sub(
    r"^\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2}\s+",
    "",
    line,
    count=1
)
print(clean)
# ERROR create_time=2026-06-01 msg=failed

如果不加开头的 ^,或者不限制范围,后面的业务时间也可能被你顺手干掉。线上清洗脚本最怕这种看起来没报错的错。

最后是 re.subn()

它和 sub() 很像,也是替换,但会多返回一个数字:替换了几次。

这个数字很有用。批量脚本里,我一般不会只关心结果,还要知道到底动了多少数据。尤其是清洗手机号、身份证、异常字符这种操作,替换次数就是一个很便宜的校验指标。

import re
rows = [
    "user=tom phone=13812345678",
    "user=jerry phone=",
    "user=lucy phone=13988887777"
]
for row in rows:
    masked, hit = re.subn(
        r"(?<!\d)(1[3-9]\d)\d{4}(\d{4})(?!\d)",
        r"\1****\2",
        row
    )
    if hit == 0:
        print(f"[WARN] 未找到手机号{row}")
        continue
    print(masked)

输出大概是这样:

user=tom phone=138****5678
[WARN] 未找到手机号: user=jerry phone=
user=lucy phone=139****7777

subn() 适合放在批处理、导入校验、日志脱敏这类场景里。它不是功能更强,而是更适合排查。脚本跑完,你至少知道命中了多少条,没命中的数据要不要丢出来看一眼。

这三个方法放一起看,区别挺清楚。

split() 管拆。字符串里分隔符不固定,用它。

sub() 管替换。脱敏、清洗、格式修正,用它。

subn() 也是替换,但顺手告诉你替换了几次。批量处理时,我更喜欢它,心里有数。

最后补一句,正则别写得太玄。

能用一条简单规则解决,就别堆十几个分支。真遇到复杂数据,宁可拆成两三步处理,中间打印一下样本,也别把所有逻辑塞进一条正则里。后面出问题的时候,你会感谢当时那个没逞强的自己。

以上就是“Python 的 re 模块中 split()、sub()、subn() 方法有什么作用?的详细内容,想要了解更多Python教程欢迎持续关注编程学习网。 

扫码二维码 获取免费视频学习资料

Python编程学习

查 看2022高级编程视频教程免费获取