pin_drop当前位置:知识文库 ❯ 图文

Python re.findall()函数详解 - 正则表达式查找所有匹配

一、概述

re.findall() 是 Python 正则表达式模块 re 中最常用的函数之一。它用于在目标字符串中查找所有与正则表达式匹配的内容,并将所有匹配结果以列表形式返回。与 re.search() 只返回第一个匹配不同,re.findall() 会扫描整个字符串,提取出所有匹配项,这在数据提取、文本分析等场景中非常实用。


二、语法

代码示例

re.findall(pattern, string, flags=0)

参数说明:

  • pattern:正则表达式模式(字符串或已编译的 Pattern 对象)

  • string:要搜索的目标字符串

  • flags:可选标志位,用于修改匹配行为(如 re.IGNORECASEre.MULTILINE 等)

返回值:返回一个列表,包含所有非重叠匹配的子串。如果没有找到匹配项,则返回空列表 []


三、基本用法

提取所有数字

使用 \d+ 模式匹配一个或多个数字:

代码示例

import re

text = "订单编号:1001,数量:50,价格:299.99元"
numbers = re.findall(r'\d+', text)
print(numbers)
# ['1001', '50', '299', '99']

提取所有单词

使用 \b\w+\b 匹配所有单词:

代码示例

import re

text = "Python is a great programming language"
words = re.findall(r'\b\w+\b', text)
print(words)
# ['Python', 'is', 'a', 'great', 'programming', 'language']

提取邮箱地址

从一段文本中提取所有邮箱地址:

代码示例

import re

text = "联系邮箱:admin@example.com,技术支持:support@test.org"
emails = re.findall(r'[\w\.-]+@[\w\.-]+\.\w+', text)
print(emails)
# ['admin@example.com', 'support@test.org']

四、代码示例

使用分组捕获提取数据

当正则表达式中包含分组(圆括号)时,re.findall() 的行为会发生变化——它返回的是分组捕获的内容,而不是整个匹配:

代码示例

import re

text = "张三:13800138000, 李四:13900139000, 王五:13700137000"

# 单个分组:返回列表,元素为分组内容
contacts = re.findall(r'(\w+):(\d+)', text)
print(contacts)
# [('张三', '13800138000'), ('李四', '13900139000'), ('王五', '13700137000')]

for name, phone in contacts:
    print(f"姓名:{name},电话:{phone}")

忽略大小写匹配

代码示例

import re

text = "Python PYTHON python PyThon"
# 使用 re.IGNORECASE 忽略大小写
matches = re.findall(r'python', text, re.IGNORECASE)
print(matches)
# ['Python', 'PYTHON', 'python', 'PyThon']

提取 HTML 标签内容

代码示例

import re

html = "<p>第一段</p><div>第二段</div><span>第三段</span>"
# 提取所有标签内的文本
contents = re.findall(r'<\w+>(.*?)</\w+>', html)
print(contents)
# ['第一段', '第二段', '第三段']

提取 URL 中的参数

代码示例

import re

url = "https://example.com/search?q=python&page=2&lang=zh"
# 提取所有查询参数
params = re.findall(r'(\w+)=(\w+)', url)
print(params)
# [('q', 'python'), ('page', '2'), ('lang', 'zh')]

# 转换为字典
param_dict = dict(params)
print(param_dict)
# {'q': 'python', 'page': '2', 'lang': 'zh'}

综合示例:分析日志文件

代码示例

import re

log_text = """
2024-01-15 08:30:22 ERROR Connection timeout
2024-01-15 08:31:15 INFO User login successful
2024-01-15 08:32:00 WARNING Disk space low
2024-01-15 08:33:45 ERROR Database connection failed
2024-01-15 08:35:10 INFO Backup completed
"""

# 提取所有错误日志
errors = re.findall(r'\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} ERROR (.+)', log_text)
print("错误日志:", errors)
# ['Connection timeout', 'Database connection failed']

# 提取所有时间
times = re.findall(r'(\d{2}:\d{2}:\d{2})', log_text)
print("所有时间点:", times)
# ['08:30:22', '08:31:15', '08:32:00', '08:33:45', '08:35:10']

五、注意事项

  • 分组影响返回值:当正则中包含分组时,re.findall() 返回的是分组内容而非整个匹配。如果只需要整个匹配,请使用非捕获分组 (?:...)

  • 非重叠匹配re.findall() 只返回非重叠的匹配。例如在字符串 "aaaa" 中搜索 "aa",只会匹配两次而不是三次

  • 空匹配问题:如果正则表达式可能匹配空字符串(如 r'a*'),re.findall() 会返回大量空字符串结果

  • 内存消耗re.findall() 会将所有匹配结果一次性加载到内存中,处理大文件时建议使用 re.finditer() 替代

  • 多行匹配:默认情况下 . 不匹配换行符,如需跨行匹配请使用 re.DOTALL 标志


六、小结

本节系统学习了 re.findall() 函数的用法。它用于在字符串中查找所有匹配项并返回列表,是数据提取最常用的正则函数。需要注意分组会改变返回值类型,非重叠匹配的特性,以及处理大量数据时的内存问题。掌握 re.findall() 后,你可以轻松完成邮箱提取、日志分析、HTML 解析等常见的文本处理任务。


七、练习题

练习1

给定一段包含多个 IP 地址的文本,使用 re.findall() 提取所有 IPv4 地址:

代码示例

text = "服务器1: 192.168.1.1, 服务器2: 10.0.0.255, 网关: 172.16.0.1"

练习2

编写一个函数,从一段文本中统计所有出现的大写单词和小写单词的数量。

练习参考答案

练习1:re.findall(r'\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b', text)
练习2:使用 re.findall(r'\b[A-Z]+\b', text) 找大写单词,re.findall(r'\b[a-z]+\b', text) 找小写单词,然后用 len() 统计

小贴士

re.findall() 是文本处理中最便捷的工具之一,但需要注意:如果处理大量数据或大文件,建议使用 re.finditer() 返回迭代器来节省内存。对于频繁使用的正则表达式,建议先用 re.compile() 预编译以提升性能。

常见问题

re.findall 和 re.finditer 有什么区别?

re.findall() 返回包含所有匹配结果的列表,一次性加载到内存。re.finditer() 返回迭代器,逐个产生 Match 对象,更节省内存且可以获取匹配的更多细节(如位置信息)。处理大数据时推荐使用 re.finditer()

为什么 re.findall 有时返回元组列表而不是字符串列表?

当正则表达式中包含分组(圆括号)时,re.findall() 会返回分组捕获的内容。单个分组返回字符串列表,多个分组返回元组列表。如果只需要完整匹配而不需要分组,可以使用非捕获分组 (?:...) 来避免这种变化。

re.findall 找不到匹配时返回什么?

当没有找到任何匹配时,re.findall() 返回空列表 [],而不是 None。这使得你可以直接对结果进行迭代或检查 len(),不需要额外的空值判断。

如何使用 re.findall 进行跨行匹配?

默认情况下 . 不匹配换行符。如果需要跨行匹配,可以传入 re.DOTALLre.S 标志:re.findall(r'

.*?
', text, re.DOTALL)

方法对比:re.findall vs re.finditer vs re.search

函数 返回值类型 匹配数量 内存占用 适用场景
re.findall() 列表(list) 所有匹配 高(一次性加载) 数据量小、需要列表操作
re.finditer() 迭代器 所有匹配 低(按需生成) 大数据量、需要位置信息
re.search() Match 对象或 None 仅第一个匹配 只需判断是否存在匹配
标签: Python正则 re.findall 正则表达式 文本处理 数据提取 Python教程

本文涉及AI创作

内容由AI创作,请仔细甄别

list快速访问

上一篇: re.search详解 - Python正则表达式搜索匹配使用指南 下一篇: Python re.finditer详解 - 迭代查找正则匹配与Match对象

poll相关推荐