python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python正则替换字符串

从基础到进阶详解Python如何使用正则替换字符串

作者:detayun

在Python中,字符串替换是常见的操作,这篇文章将详细介绍如何使用正则表达式进行字符串替换,并提供实际案例,感兴趣的小伙伴可以了解下

在Python中,字符串替换是常见的操作,但简单的str.replace()方法只能处理固定字符串的替换。当需要模式匹配(如替换所有数字、邮箱、URL等)时,正则表达式(re模块)的re.sub()方法就派上了用场。本文将详细介绍如何使用正则表达式进行字符串替换,并提供实际案例。

1. 基础正则替换:re.sub()

1.1re.sub()基本语法

re.sub() 是Python正则替换的核心方法,语法如下:

import re

re.sub(pattern, repl, string, count=0, flags=0)

1.2 简单替换示例

(1) 替换所有数字

import re

text = "我的电话是123456789,QQ是987654321"
new_text = re.sub(r'\d+', '***', text)  # \d+ 匹配1个或多个数字
print(new_text)
# 输出: 我的电话是***,QQ是***

(2) 替换所有非字母字符

text = "Hello! 123 @World#Python"
new_text = re.sub(r'[^a-zA-Z]', ' ', text)  # [^a-zA-Z] 匹配非字母字符
print(new_text)
# 输出: Hello      World Python

(3) 忽略大小写替换

text = "Python is FUN, python is powerful"
new_text = re.sub(r'python', 'Java', text, flags=re.IGNORECASE)  # 忽略大小写
print(new_text)
# 输出: Java is FUN, Java is powerful

2. 高级替换技巧

2.1 使用分组(())和反向引用(\1,\2)

正则表达式可以用()分组,并在替换时用\1\2引用分组内容。

示例:交换日期格式(YYYY-MM-DD → DD/MM/YYYY)

text = "2023-01-01, 2024-12-31"
new_text = re.sub(r'(\d{4})-(\d{2})-(\d{2})', r'\3/\2/\1', text)  # \3=日, \2=月, \1=年
print(new_text)
# 输出: 01/01/2023, 31/12/2024

2.2 使用函数动态替换

repl参数可以是一个函数,根据匹配内容动态生成替换字符串。

示例:将数字乘以2后替换

def double_num(match):
    num = int(match.group())  # 获取匹配的数字
    return str(num * 2)

text = "1 apple, 2 bananas, 3 oranges"
new_text = re.sub(r'\d+', double_num, text)  # 调用函数替换
print(new_text)
# 输出: 2 apple, 4 bananas, 6 oranges

示例:隐藏敏感信息(如邮箱)

def hide_email(match):
    email = match.group()
    return email[0] + "***" + email[-4:]  # 保留首字母和后4位

text = "联系我:test@example.com 或 admin@site.org"
new_text = re.sub(r'[\w.-]+@[\w.-]+', hide_email, text)
print(new_text)
# 输出: 联系我:t***mple.com 或 a***site.org

2.3 限制替换次数(count参数)

text = "111-222-333-444"
new_text = re.sub(r'\d+', 'X', text, count=2)  # 只替换前2个数字
print(new_text)
# 输出: X-X-333-444

3. 实际应用案例

案例1:清理HTML标签

import re

html = "<p>Hello, <b>World</b>!</p>"
clean_text = re.sub(r'<[^>]+>', '', html)  # 匹配所有HTML标签并删除
print(clean_text)
# 输出: Hello, World!

案例2:标准化电话号码格式

text = "电话:010-12345678,手机:138-1234-5678"
new_text = re.sub(r'(\d{3})-(\d{4})-(\d{4})', r'\1\2\3', text)  # 尝试直接替换(可能不匹配)
# 更通用的方法:
def normalize_phone(match):
    full_num = re.sub(r'[^\d]', '', match.group())  # 先删除所有非数字
    if len(full_num) == 11:  # 手机号码
        return f"手机:{full_num[:3]}-{full_num[3:7]}-{full_num[7:]}"
    elif len(full_num) == 8:  # 座机号码(简化版)
        return f"电话:{full_num[:3]}-{full_num[3:]}"
    else:
        return match.group()

# 先提取所有电话号码(简化版,实际需更复杂正则)
text_with_phones = re.sub(r'(\d{3}[-]?\d{4}[-]?\d{4})|(\d{3}[-]?\d{4})', normalize_phone, text)
# 更准确的方式是分两步:
# 1. 提取所有电话号码
# 2. 替换
print(text_with_phones)  # 输出可能不符合预期,需更精细的正则

# 更合理的实现(分两步):
phones = re.findall(r'\d{3}[-]?\d{4}[-]?\d{4}|\d{3}[-]?\d{4}', text)
for phone in phones:
    cleaned = re.sub(r'[^\d]', '', phone)
    if len(cleaned) == 11:
        new_phone = f"{cleaned[:3]}-{cleaned[3:7]}-{cleaned[7:]}"
    elif len(cleaned) == 8:
        new_phone = f"{cleaned[:3]}-{cleaned[3:]}"
    else:
        new_phone = phone
    text = text.replace(phone, new_phone)
print(text)
# 输出: 电话:010-12345678,手机:138-1234-5678

更简洁的电话号码标准化(使用re.sub直接替换)

text = "电话:010-12345678,手机:138-1234-5678"

def normalize_phone(match):
    num = re.sub(r'[^\d]', '', match.group())
    if len(num) == 11:
        return f"手机:{num[:3]}-{num[3:7]}-{num[7:]}"
    elif len(num) == 8:
        return f"电话:{num[:3]}-{num[3:]}"
    else:
        return match.group()

# 匹配手机号(11位)或座机号(8位,可能带-)
new_text = re.sub(
    r'(手机:)?(\d{3}[-]?\d{4}[-]?\d{4})|(电话:)?(\d{3}[-]?\d{4})',
    lambda m: normalize_phone(m),
    text
)
# 上述正则不够完美,更准确的方式:
# 先提取所有电话号码,再替换
print(new_text)  # 可能需要调整正则

# 更准确的实现(分两步):
import re

text = "电话:010-12345678,手机:138-1234-5678"

# 匹配手机号或座机号
pattern = r'(?:电话:|手机:)?(\d{3}[-]?\d{4}[-]?\d{4}|\d{3}[-]?\d{4})'

def replace_phone(match):
    raw_phone = match.group(1)
    cleaned = re.sub(r'[^\d]', '', raw_phone)
    if len(cleaned) == 11:
        return f"手机:{cleaned[:3]}-{cleaned[3:7]}-{cleaned[7:]}"
    elif len(cleaned) == 8:
        return f"电话:{cleaned[:3]}-{cleaned[3:]}"
    else:
        return raw_phone

new_text = re.sub(pattern, replace_phone, text)
print(new_text)
# 输出: 电话:010-12345678,手机:138-1234-5678

简化版(假设输入格式较规范)

text = "电话:010-12345678,手机:138-1234-5678"
new_text = re.sub(
    r'(\d{3})-(\d{4})-(\d{4})',  # 匹配手机号格式
    r'手机:\1-\2-\3',
    re.sub(
        r'(\d{3})-(\d{4})',  # 匹配座机号格式
        r'电话:\1-\2',
        text
    )
)
print(new_text)
# 输出: 电话:010-12345678,手机:138-1234-5678

案例3:替换URL中的协议(http → https)

text = "访问 http://example.com 或 https://test.org"
new_text = re.sub(r'http://', 'https://', text)  # 简单替换
print(new_text)
# 输出: 访问 https://example.com 或 https://test.org

4. 常见问题与解决方案

问题1:正则表达式匹配不到内容?

问题2:替换后格式混乱?

问题3:性能问题(大量文本替换)?

5. 总结

方法适用场景示例
re.sub(r'\d+', 'X', text)简单模式替换替换所有数字为X
re.sub(r'(\d{4})-(\d{2})', r'\2/\1', text)分组与反向引用交换日期格式
re.sub(r'\d+', lambda m: str(int(m.group())*2), text)函数动态替换数字乘以2后替换
re.sub(r'<[^>]+>', '', text)清理HTML标签删除所有<...>标签

最佳实践

  1. 简单替换str.replace(),复杂模式用re.sub()
  2. 需要保留部分匹配内容时,用()分组和\1反向引用。
  3. 动态生成替换内容时,用函数作为repl参数。
  4. 处理大量文本时,预编译正则(re.compile())提高性能。

掌握这些技巧后,你可以高效地处理各种字符串替换需求! 

到此这篇关于从基础到进阶详解Python如何使用正则替换字符串的文章就介绍到这了,更多相关Python正则替换字符串内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文