ZetCode

Python re.finditer() 函数

最后修改于 2025 年 4 月 20 日

re.finditer 简介

re.finditer 函数是 Python 的 re 模块中用于模式匹配的强大工具。 它返回一个迭代器,为所有非重叠匹配生成匹配对象。

与返回字符串的 re.findall 不同,finditer 提供带有详细匹配信息的匹配对象。 这包括位置和捕获组。

该函数对于大型文本具有内存效率,因为它以惰性方式处理匹配。 当您需要匹配详细信息而不仅仅是文本时,它是理想的选择。

基本语法

re.finditer 的语法很简单

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

pattern 是要匹配的正则表达式。 string 是要搜索的文本。 可选的 flags 修改匹配行为。

基本模式匹配

让我们从一个简单的例子开始,找到文本中的所有元音。

basic_finditer.py
#!/usr/bin/python

import re

text = "The quick brown fox jumps over the lazy dog"
pattern = r'[aeiou]'

for match in re.finditer(pattern, text):
    print(f"Found '{match.group()}' at position {match.start()}")

此示例查找文本中的所有元音并打印每个元音及其位置。 匹配对象提供 groupstart 方法。

pattern = r'[aeiou]'

此模式匹配任何单个元音字符。 方括号定义一个字符类。

for match in re.finditer(pattern, text):

finditer 调用返回一个匹配对象的迭代器。 我们循环遍历它们以处理每个匹配。

查找具有特定模式的单词

让我们在文本中查找所有以“q”或“j”开头的单词。

word_patterns.py
#!/usr/bin/python

import re

text = "The quick brown fox jumps over the lazy dog"
pattern = r'\b[qj]\w+\b'

for match in re.finditer(pattern, text, re.IGNORECASE):
    print(f"Found word: {match.group()}")
    print(f"Start: {match.start()}, End: {match.end()}")

这使用单词边界 (\b) 来匹配整个单词。 \w+ 匹配后续的单词字符。

re.IGNORECASE 标志使匹配不区分大小写。 匹配对象提供开始和结束位置。

提取电子邮件地址

以下是如何从文本中提取电子邮件地址,并显示详细位置。

emails.py
#!/usr/bin/python

import re

text = "Contact us at support@example.com or sales@example.org"
pattern = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'

for match in re.finditer(pattern, text):
    print(f"Email: {match.group()}")
    print(f"Position: {match.span()}")
    print(f"Full match: {text[match.start():match.end()]}")

此模式匹配标准电子邮件格式。 span 方法返回一个 (start, end) 位置的元组。

我们演示了如何通过 match.group() 和切片原始字符串来访问匹配的文本。

查找带有分组的日期

此示例提取日期,同时捕获日、月和年组。

dates.py
#!/usr/bin/python

import re

text = "Dates: 2023-12-25, 2024-01-01, 2024-02-14"
pattern = r'(\d{4})-(\d{2})-(\d{2})'

for match in re.finditer(pattern, text):
    print(f"Full date: {match.group(0)}")
    print(f"Year: {match.group(1)}, Month: {match.group(2)}")
    print(f"Day: {match.group(3)} at {match.start()}")

括号创建捕获组。 组 0 始终是完整匹配。 后续组匹配带括号的子模式。

这对于结构化数据提取非常有用,您既需要完整匹配及其组成部分。

使用先行断言的重叠匹配

finditer 通常查找非重叠匹配。 这是使用先行断言查找重叠的方法。

overlapping.py
#!/usr/bin/python

import re

text = "abracadabra"
pattern = r'(?=(\w{3}))'  # Lookahead for 3-letter sequences

for match in re.finditer(pattern, text):
    print(f"Found: {match.group(1)} at {match.start()}")

正向先行断言 (?=...) 允许查找重叠匹配。 实际匹配在组 1 中捕获。

此技术对于查找文本中所有可能的 n-gram 或滑动窗口很有用。

多行文本处理

此示例演示了如何处理带有行号的多行文本。

multiline.py
#!/usr/bin/python

import re

text = """First line
Second line with IMPORTANT data
Third line
Fourth line with CRITICAL information"""

pattern = r'(IMPORTANT|CRITICAL)'
lines = text.splitlines()

for match in re.finditer(pattern, text):
    line_no = text[:match.start()].count('\n') + 1
    print(f"Found '{match.group()}' in line {line_no}:")
    print(f"> {lines[line_no-1]}")

我们通过计算匹配项之前的新行来计算行号。 实际的行内容是从预先分割的列表中检索的。

这种方法对于日志处理或文档分析非常有用,其中行上下文很重要。

性能注意事项

使用 re.finditer 处理大型文本时,请考虑以下性能提示

来源

Python re.finditer() 文档

本教程介绍了 Python 的 re.finditer 函数的本质方面。 掌握这种基于迭代器的方法将使您的模式匹配代码更加高效和灵活。

作者

我叫 Jan Bodnar,是一位充满热情的程序员,拥有丰富的编程经验。 我自 2007 年以来一直在撰写编程文章。 迄今为止,我已经撰写了超过 1,400 篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 Python 教程