Python 将字符串中的所有数字替换为星号(长文讲解)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观
在编程和数据处理中,将字符串中的敏感数字替换为星号是一个常见的需求。例如,在用户注册时隐藏身份证号、银行卡号等信息,或是在日志脱敏场景中保护隐私数据。本文将深入探讨如何用 Python 实现这一功能,并通过不同方法对比、代码示例和实际案例,帮助读者理解其核心原理与应用场景。
一、字符串基础与替换逻辑
字符串的不可变性
Python 中的字符串是不可变对象,这意味着对字符串的任何修改都会生成新的字符串。例如:
original = "Hello123"
new_str = original.replace("123", "***")
print(new_str) # 输出 "Hello***"
这里的 replace()
方法会创建新字符串,而非直接修改原字符串。
直接替换的局限性
若需替换所有数字,逐个字符替换会更灵活。例如:
text = "Password1234"
result = ""
for char in text:
if char.isdigit(): # 判断是否为数字
result += "*"
else:
result += char
print(result) # 输出 "Password****"
此方法逐个检查字符,但效率较低,尤其在处理长字符串时可能不够高效。
二、正则表达式(Regex)的灵活应用
正则表达式简介
正则表达式是文本模式匹配的利器,可以高效定位并替换字符串中的特定模式。在 Python 中,re
模块提供了正则表达式功能。
核心语法
\d
:匹配任意单个数字(0-9)。+
:匹配前一个字符 1 次或多次。re.sub(pattern, replacement, string)
:替换匹配到的内容。
实现数字替换的代码示例
import re
def replace_numbers_with_asterisks(text):
return re.sub(r"\d+", "*", text)
print(replace_numbers_with_asterisks("Phone: 123-456-7890")) # 输出 "Phone: *-*-*"
print(replace_numbers_with_asterisks("Year2023")) # 输出 "Year*"
问题与优化:
上述代码将连续数字替换为单个星号,若需替换为与原数字长度相同的星号(例如 123
→ ***
),可使用回调函数:
def replace_with_same_length(match):
return "*" * len(match.group())
def precise_replace(text):
return re.sub(r"\d+", replace_with_same_length, text)
print(precise_replace("ID: 123456")) # 输出 "ID: ******"
三、进阶方法与代码优化
方法 1:使用 re.compile()
提升性能
若需多次调用正则表达式,预编译模式可减少重复解析开销:
import re
pattern = re.compile(r"\d+")
def optimized_replace(text):
return pattern.sub("*", text)
for _ in range(1000):
optimized_replace("Test123")
方法 2:列表推导式与 join()
组合
通过遍历字符并组合新字符串,代码更简洁:
def list_comprehension_approach(text):
return "".join(["*" if c.isdigit() else c for c in text])
print(list_comprehension_approach("2023 is the year")) # 输出 "** is the year"
方法 3:处理 Unicode 数字(可选)
若需支持 Unicode 数字(如罗马数字、汉字数字),可扩展匹配模式:
def replace_unicode_numbers(text):
return re.sub(r"[\d\u0660-\u0669\u0e50-\u0e59]+", "*", text)
print(replace_unicode_numbers("泰语数字:๑๒๓")) # 输出 "泰语数字:***"
四、性能对比与场景选择
不同方法的效率测试
通过 timeit
模块对比三种方法:
import timeit
test_str = "a1b2c3d4e5" * 1000
def method1(text):
return re.sub(r"\d+", "*", text)
def method2(text):
return "".join(["*" if c.isdigit() else c for c in text])
def method3(text):
return re.sub(r"\d+", "*", text, flags=re.ASCII)
print("Method1:", timeit.timeit(lambda: method1(test_str), number=1000))
print("Method2:", timeit.timeit(lambda: method2(test_str), number=1000))
print("Method3:", timeit.timeit(lambda: method3(test_str), number=1000))
常见结果:
- 正则表达式(Method1)通常最快,因其底层用 C 实现。
- 列表推导式(Method2)次之,适合简单场景。
- 若需禁用 Unicode 支持(如纯 ASCII 字符),可添加
re.ASCII
标志加速(Method3)。
场景选择建议
场景需求 | 推荐方法 | 优势与适用性 |
---|---|---|
基础替换(简单字符串) | 列表推导式或直接循环 | 代码直观,适合新手理解 |
高效处理长字符串 | 正则表达式(re.sub() ) | 底层优化,速度最快 |
需保留数字长度 | 回调函数 + 正则表达式 | 精确控制替换后的星号数量 |
多语言/Unicode 支持 | 自定义 Unicode 正则模式 | 扩展匹配范围,但需注意性能影响 |
五、实际案例与扩展应用
案例 1:日志脱敏
假设日志内容包含用户 ID 和订单号:
def log_sanitizer(log_entry):
return re.sub(r"\b\d{4,}\b", "****", log_entry)
print(log_sanitizer("User 123456 logged in. Order #7890123 processed."))
此方法通过 \b
匹配单词边界,避免替换非数字内容。
案例 2:密码强度验证中的替换
在密码设置时隐藏部分字符:
def hide_password_chars(password):
return re.sub(r"(?<=\w)\d(?=\w)|\d", "*", password)
print(hide_password_chars("Pass123word")) # 输出 "Pass**3word"
此正则通过正向预查((?<=\w)
)和后向预查((?=\w)
)定位中间的数字,实现部分隐藏。
六、常见问题与解决方案
问题 1:替换后星号数量不足
原因:默认正则模式将连续数字视为一个整体替换为单个星号。
解决:使用回调函数或 re.finditer()
获取匹配位置:
def replace_with_length(text):
result = list(text)
for match in re.finditer(r"\d+", text):
start, end = match.span()
result[start:end] = ["*"] * (end - start)
return "".join(result)
print(replace_with_length("1234")) # 输出 "****"
问题 2:特殊字符干扰
场景:字符串中存在类似数字的符号(如 ²
、①
)。
解决:通过 Unicode 范围或自定义模式精确匹配:
re.sub(r"[\d\u2460-\u24FF]+", "*", "测试①号:2²")
七、结论
将字符串中的数字替换为星号是 Python 中一项实用技能,其核心在于理解字符串操作逻辑与正则表达式的灵活运用。通过本文的讲解,读者可以掌握:
- 字符串不可变性与基础替换方法;
- 正则表达式在模式匹配中的高效性;
- 不同场景下的代码优化技巧与性能对比。
无论是处理用户隐私数据、日志脱敏还是密码强度验证,这些方法都能提供灵活的解决方案。建议读者通过实际项目练习,进一步巩固对正则表达式和字符串操作的理解。
通过本文的学习,您已掌握了 Python 中字符串数字替换的核心技术。若需更复杂的数据处理需求,可进一步探索 re
模块的高级功能或第三方库(如 fuzzywuzzy
),但基础方法的熟练运用仍是解决问题的第一步。