pin_drop当前位置:知识文库 ❯ 图文
Python re.findall()函数详解 - 正则表达式查找所有匹配
一、概述
re.findall() 是 Python 正则表达式模块 re 中最常用的函数之一。它用于在目标字符串中查找所有与正则表达式匹配的内容,并将所有匹配结果以列表形式返回。与 re.search() 只返回第一个匹配不同,re.findall() 会扫描整个字符串,提取出所有匹配项,这在数据提取、文本分析等场景中非常实用。
二、语法
代码示例
re.findall(pattern, string, flags=0)参数说明:
-
pattern:正则表达式模式(字符串或已编译的 Pattern 对象) -
string:要搜索的目标字符串 -
flags:可选标志位,用于修改匹配行为(如re.IGNORECASE、re.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.DOTALL 或 re.S 标志:re.findall(r'。
方法对比:re.findall vs re.finditer vs re.search
| 函数 | 返回值类型 | 匹配数量 | 内存占用 | 适用场景 |
|---|---|---|---|---|
re.findall() |
列表(list) | 所有匹配 | 高(一次性加载) | 数据量小、需要列表操作 |
re.finditer() |
迭代器 | 所有匹配 | 低(按需生成) | 大数据量、需要位置信息 |
re.search() |
Match 对象或 None | 仅第一个匹配 | 低 | 只需判断是否存在匹配 |
本文涉及AI创作
内容由AI创作,请仔细甄别