re.finditer和re.findall之间的不同行为

时间:2010-09-21 22:39:37

标签: python regex

我使用以下代码:

CARRIS_REGEX=r'<th>(\d+)</th><th>([\s\w\.\-]+)</th><th>(\d+:\d+)</th><th>(\d+m)</th>'
pattern = re.compile(CARRIS_REGEX, re.UNICODE)
matches = pattern.finditer(mailbody)
findall = pattern.findall(mailbody)

但是finditer和findall正在寻找不同的东西。 Findall确实找到了给定字符串中的所有匹配项。但是finditer只找到第一个,返回一个只有一个元素的迭代器。

如何使finditer和findall的行为方式相同?

由于

4 个答案:

答案 0 :(得分:27)

我不能在这里重现这一点。尝试过使用Python 2.7和3.1。

finditerfindall之间的一个区别是前者返回正则表达式匹配对象,而另一个返回匹配的捕获组的元组(如果没有捕获组,则返回整个匹配)。 / p>

所以

import re
CARRIS_REGEX=r'<th>(\d+)</th><th>([\s\w\.\-]+)</th><th>(\d+:\d+)</th><th>(\d+m)</th>'
pattern = re.compile(CARRIS_REGEX, re.UNICODE)
mailbody = open("test.txt").read()
for match in pattern.finditer(mailbody):
    print(match)
print()
for match in pattern.findall(mailbody):
    print(match)

打印

<_sre.SRE_Match object at 0x00A63758>
<_sre.SRE_Match object at 0x00A63F98>
<_sre.SRE_Match object at 0x00A63758>
<_sre.SRE_Match object at 0x00A63F98>
<_sre.SRE_Match object at 0x00A63758>
<_sre.SRE_Match object at 0x00A63F98>
<_sre.SRE_Match object at 0x00A63758>
<_sre.SRE_Match object at 0x00A63F98>

('790', 'PR. REAL', '21:06', '04m')
('758', 'PORTAS BENFICA', '21:10', '09m')
('790', 'PR. REAL', '21:14', '13m')
('758', 'PORTAS BENFICA', '21:21', '19m')
('790', 'PR. REAL', '21:29', '28m')
('758', 'PORTAS BENFICA', '21:38', '36m')
('758', 'SETE RIOS', '21:49', '47m')
('758', 'SETE RIOS', '22:09', '68m')

如果您想从finditer获得与findall相同的输出,则需要

for match in pattern.finditer(mailbody):
    print(tuple(match.groups()))

答案 1 :(得分:5)

你不能让他们表现得一样,因为他们是不同的。如果您真的想要创建finditer的结果列表,那么您可以使用列表推导:

>>> [match for match in pattern.finditer(mailbody)]
[...]

通常,使用for循环来访问re.finditer返回的匹配项:

>>> for match in pattern.finditer(mailbody):
...     ...

答案 2 :(得分:4)

  

<强> re.findall(pattern.string)

     

findall()返回string中pattern的所有非重叠匹配    作为字符串列表。

     

<强> re.finditer()

     

finditer()返回 可调用对象

     

在这两个函数中,字符串从左向右扫描   匹配按订单返回。

答案 3 :(得分:2)

我从Regular expression operations中的Python 2.* Documentation得到了这个例子,并在此作了一些修改,详细描述了这个例子。为了解释整个示例,让我们获取字符串类型的变量调用,

text = "He was carefully disguised but captured quickly by police."

compile类型的正则表达式模式为

regEX = r"\w+ly"
pattern = re.compile(regEX)

\w的意思是匹配任何单词字符(字母数字和下划线)+的意思是匹配1个或更多个前面的标记和整个意思是选择任何以{em> ly结尾的单词。只有两个2个单词(“仔细地”和“迅速地”)满足上述正则表达式。

在进入re.findall()re.finditer()之前,让我们看看re.search()Python 2.* Documentation中的含义。

  

扫描字符串以查找正则表达式模式产生匹配项的第一个位置,然后返回相应的MatchObject实例。如果字符串中没有位置与模式匹配,则返回None;否则,返回None。请注意,这不同于在字符串中的某个位置找到零长度匹配项。

下面的代码行使您对re.search()有了基本的了解。

search = pattern.search(text)
print(search)
print(type(search))

#output
<re.Match object; span=(7, 16), match='carefully'>
<class 're.Match'>

它将根据re.MatchObject生成具有13种受支持的方法和属性的类类型对象Python 2.* Documentation。此span()方法由text变量中匹配单词的起点和终点(在上面的示例中为7和16)组成。 re.search()方法只考虑第一个匹配项,否则返回None

让我们进入这个问题,在此之前,先了解re.finditer()Python 2.* Documentation中的含义。

  

返回一个迭代器,该迭代器在字符串RE模式的所有非重叠匹配上产生MatchObject实例。从左到右扫描该字符串,并以找到的顺序返回匹配项。空匹配项包含在结果中。

后面的代码行使您对re.finditer()有了基本的了解。

finditer = pattern.finditer(text)
print(finditer)
print(type(finditer))

#output
<callable_iterator object at 0x040BB690>
<class 'callable_iterator'>

以上示例为我们提供了需要循环的Iterator Objects。这显然不是我们想要的结果。让我们循环finditer并查看此Iterator Objects的内容。

for anObject in finditer:
    print(anObject)
    print(type(anObject))
    print()

#output
<re.Match object; span=(7, 16), match='carefully'>
<class 're.Match'>

<re.Match object; span=(40, 47), match='quickly'>
<class 're.Match'>

此结果与我们之前获得的re.search()结果非常相似。但是我们可以在上面的输出<re.Match object; span=(40, 47), match='quickly'>中看到新结果。正如我之前在Python 2.* Documentation中提到的,re.search()扫描字符串以查找正则表达式模式产生匹配项的第一个位置,而re.finditer()扫描字符串以查找正则表达式模式产生匹配的所有位置,并返回比re.findall()方法更详细的信息。

re.findall()Python 2.* Documentation中是什么意思。

  

以字符串列表形式返回字符串中所有不重复的模式匹配项。从左到右扫描该字符串,并以找到的顺序返回匹配项。如果该模式中存在一个或多个组,则返回一个组列表;否则,返回一个列表。如果模式包含多个组,则这将是一个元组列表。空匹配项包含在结果中。

让我们了解re.findall()中会发生什么。

findall = pattern.findall(text)
print(findall)
print(type(findall))

#output
['carefully', 'quickly']
<class 'list'>

此输出仅为我们提供text变量中的匹配单词,否则返回空的list。输出中的listre.MatchObject中的match属性类似。

这是完整的代码,我在Python 3.7中尝试过。

import re

text = "He was carefully disguised but captured quickly by police."

regEX = r"\w+ly"
pattern = re.compile(regEX)

search = pattern.search(text)
print(search)
print(type(search))
print()

findall = pattern.findall(text)
print(findall)
print(type(findall))
print()

finditer = pattern.finditer(text)
print(finditer)
print(type(finditer))
print()
for anObject in finditer:
    print(anObject)
    print(type(anObject))
    print()