广告

Python正则表达式怎么用_re模块?实战教程带你从零基础到高效文本处理

1. 基本概念与安装

1.1 什么是 Python 的 re 模块

在 Python 中,正则表达式用于描述文本的匹配模式,re 模块提供了一组强大接口来编译、匹配、查找和替换文本。通过这套工具,可以实现高效的文本检索、抽取和清洗工作,是数据处理和文本分析的重要利器。

re 模块的核心在于把正则表达式模式转换成可执行对象,然后对目标文本执行匹配操作。它的主要方法包括 compilematchsearchfindallfinditersubsplit 等。掌握这些方法后,你就能把复杂的文本处理需求转化为简单的模式匹配逻辑。

下面给出一个最小示例,展示如何使用 re 模块来查找文本中的一个简单模式。请注意使用原始字符串以避免转义带来的困扰。

import retext = "我的电话是 110-1234-5678,请保密。"
pattern = r'\b\d{3}-\d{4}-\d{4}\b'  # 简单的电话号码格式
m = re.search(pattern, text)
print(m.group() if m else "未匹配")

1.2 正则表达式的核心要点

正则表达式的核心要点包括 字符集元字符量词分组、以及锚点等概念。通过这些元素可以构造出灵活的模式来匹配各种文本结构。理解这些概念,是实现高效文本处理的基础。

在实际场景中,你会频繁遇到的模式构造包括:字符集合如 [a-zA-Z0-9],量词如 {n,m}、?、*、+,分组如 (...),以及用于定位位置的 锚点如 ^、$。掌握它们后,可以用极少的代码完成复杂的文本筛选。

为了避免转义带来的困难,推荐始终使用 原始字符串(以 r 开头)来表示正则表达式模式。

import re# 分组示例:提取区号与号码
text = "联系号码: (010) 1234-5678 或 021-9876-5432"
pattern = r'\((\d{3})\)\s*(\d{4}-\d{4})'
m = re.search(pattern, text)
if m:print("区号:", m.group(1))print("号码:", m.group(2))

2. re 模块的核心方法

2.1 常用方法:compile、match、search、fullmatch

使用 re.compile 可以把正则表达式编译为一个模式对象,后续对同一模式多次使用时可以提升性能。相比 matchsearch 会在整个文本中进行搜索,而 fullmatch 则需要整段文本全部匹配才算成功。

下面的示例演示如何编译模式并使用 matchsearch 的差异,以及如何通过模式对象进行多次匹配。

import retext = "邮箱: alice@example.com, 他的站点是 example.org"# 使用 compile 提升重复使用的性能
pattern = re.compile(r'[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}')m1 = pattern.match(text)
s = text.upper()
m2 = pattern.search(s)print("是否从头匹配:", bool(m1))
print("在大文本中搜索到的结果:", m2.group() if m2 else None)

2.2 findall 与 finditer 的区别

findall 会返回所有匹配的文本(组成一个列表),finditer 则返回一个迭代器,可以逐个遍历每个匹配对象,适合大文本或需要逐步处理的场景。

在文本中提取所有单词的示例,展示两者的用法差异:

import retext = "Hello world 123, 你好 世界 456"
# 找出所有单词字符序列
pattern = r'\b\w+\b'# findall 直接返回列表
all_words = re.findall(pattern, text)# finditer 返回迭代器,可以逐个处理
iter_words = [m.group() for m in re.finditer(pattern, text)]print("findall:", all_words)
print("finditer:", iter_words)

3. 实战案例:从零基础到高效文本处理

3.1 提取邮箱与手机号

在实际数据处理中,快速提取邮箱和手机号是最常见的任务之一。通过组合合适的模式,可以在一段文本中高效识别并提取所需信息。邮箱模式通常关注局部字符集与域名结构,手机号模式则关注分隔符和位数的稳定性。

以下代码演示如何同时提取文本中的邮箱与手机号,并演示如何使用组来定位不同的信息段。请注意使用原始字符串以避免转义混乱。

Python正则表达式怎么用_re模块?实战教程带你从零基础到高效文本处理

import retext = """
联系信息
邮箱: john.doe@example.com
备用邮箱: 末尾处@sample.co.uk
手机号: 188-1234-5678, 010-5555-0000
"""email_pattern = r'[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}'
phone_pattern = r'\b\d{3,4}-\d{3,4}-\d{4}\b'emails = re.findall(email_pattern, text)
phones = re.findall(phone_pattern, text)print("提取的邮箱:", emails)
print("提取的手机号:", phones)

通过 findall 可一次性得到邮箱与手机号的完整列表,若需要更丰富的上下文信息,可以改用 finditer 逐条处理。

另外,还可以把邮箱与手机号归并到一个字典中,便于后续的数据清洗和存储。

import retext = "联系邮箱:alex@example.com,电话:020-8888-7777"
patterns = {'email': r'[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}','phone': r'\b\d{3,4}-\d{3,4}-\d{4}\b'
}results = {k: re.findall(v, text) for k, v in patterns.items()}
print(results)

3.2 替换与清洗文本

文本清洗通常需要将敏感信息替换为掩码、删除多余空格、统一日期格式等。re.sub 是实现替换的核心函数,通过传入替换字符串或回调函数,可以实现灵活的文本清洗策略。

下面的示例演示如何把邮箱地址替换为掩码形式,以及如何将多个空白字符压缩为单个空格。这样的处理在日志分析和数据导入时非常有用。

import retext = "用户 alice@example.com 及其主页 http://example.com   的访问记录。"
# 将邮箱替换为掩码
cleaned = re.sub(r'[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}', '[EMAIL]', text)
# 将连续空格压缩成一个空格
cleaned = re.sub(r'\s+', ' ', cleaned).strip()print("清洗后的文本:", cleaned)

如果需要在替换时动态控制替换内容,可以传入一个回调函数到 re.sub,根据匹配结果生成不同的替换文本。

import retext = "订单号: 12345, 状态: 已发货"
# 将数字替换为星号,保持长度信息
def mask_digits(m):s = m.group()return '*' * len(s)result = re.sub(r'\d+', mask_digits, text)
print("部分掩码替换:", result)

4. 高级技巧与性能优化

4.1 使用原始字符串与忽略大小写

在实际开发中,原始字符串(以 r 开头)可以让我们避免大量转义符号带来的困扰。使用 re.IGNORECASEre.I 可以实现不区分大小写的匹配,提升灵活性。

下面展示一个统一大小写的示例,提取不区分大小写的关键字出现位置。

import retext = "Python、python、PYTHON 都属于同一语言。"
pattern = r'python'matches = list(re.finditer(pattern, text, flags=re.IGNORECASE))
print("匹配数量:", len(matches))
for m in matches:print("位置:", m.span(), "文本:", m.group())

4.2 使用 verbose 模式与命名分组

当正则表达式变得复杂时, re.VERBOSE 可以让我们通过空格和注释来提升可读性,同时使用 (?P<name>pattern) 的命名分组方便后续提取。

示例演示如何在 verbose 模式下编写并提取命名分组的数据。

import repattern = r'''(?P\(\d{3,4}\))?      # 区号,可选\s*(?P\d{3,4}-\d{3,4}-\d{4})  # 主号码
'''
text = "联系电话: (010) 1234-5678"m = re.search(pattern, text, flags=re.VERBOSE)
if m:print("区域:", m.group('area'))print("号码:", m.group('phone'))

广告

后端开发标签