为什么在Python中re.findall()和re.finditer()给出的结果不同?

5

我写了这个正则表达式:

p = re.compile(r'''
\[\[            #the first [[
[^:]*?          #no :s are allowed
.*?             #a bunch of chars
(
\|              #either go until a |
|\]\]           #or the last ]]
)
                ''', re.VERBOSE)

我希望使用re.findall来获取一些字符串中所有匹配的部分。我写了一些测试代码,但给出的结果很奇怪。
这是代码:
g = p.finditer('   [[Imae|Lol]]     [[sdfef]]')
print g
for elem in g:
    print elem.span()
    print elem.group()

给我这个输出:

(3, 10)
[[Imae|
(20, 29)
[[sdfef]] 

完全有道理,对吧?但是当我这样做时:
h = p.findall('   [[Imae|Lol]]     [[sdfef]]')
for elem in h:
    print elem

输出结果如下:
|
]]  

为什么findall()和finditer()的结果不同呢?
5个回答

7

Findall返回匹配组的列表。你的正则表达式中的括号定义了一个查找所有认为你想要的组,但你不需要这些组。(?:...)是一个非捕获括号。将你的正则表达式改为:

'''
\[\[            #the first [[
[^:]*?          #no :s are allowed
.*?             #a bunch of chars
(?:             #non-capturing group
\|              #either go until a |
|\]\]           #or the last ]]
)
                '''

问题解决了!我忘记了findall的那一点...谢谢! - Aaron Brown

3
当您在使用re.findall()时,如果您的正则表达式中有分组(括号表达式),它会返回与这些分组匹配的。在这里,您只有一个组,它是在末尾的 | 或者 ]] 符号。另一方面,在使用 re.finditer() 的代码中,您没有指定特定的组,因此它会返回整个字符串。
您可以通过在整个正则表达式或者仅在您要提取的部分周围加上括号来让 re.findall() 返回您期望的结果。假设您正在解析维基链接,那么这将是第4行的“一堆字符”。例如:
p = re.compile(r'''
\[\[            #the first [[
[^:]*?          #no :s are allowed
(.*?)           #a bunch of chars
(
\|              #either go until a |
|\]\]           #or the last ]]
)
                ''', re.VERBOSE)

p.findall('   [[Imae|Lol]]     [[sdfef]]')

返回:

[('Imae', '|'), ('sdfef', ']]')]

哇,现在一切都清晰了。你做得很好,理解了我的意图。 - Aaron Brown

1

我认为findall()文档中的关键部分是:

如果模式中存在一个或多个组,则返回一个组列表;如果模式有多个组,则这将是一个元组列表。

你的正则表达式在管道符或闭合的]]周围有一个组:

(
\|              #either go until a |
|\]\]           #or the last ]]
)

finditer() 没有任何这样的子句。


1

它们不返回相同的内容。以下是来自文档的一些片段:

findall 返回一个字符串列表。 如果模式中存在一个或多个组,则返回一个组列表; 如果模式有多个组,则这将是一个元组列表。

finditer 返回一个迭代器, 产生MatchObject实例。


0

来自Python文档:

返回字符串中模式的所有非重叠匹配项,作为字符串列表。字符串从左到右扫描,并按找到的顺序返回匹配项。如果模式中存在一个或多个组,则返回一个组列表;如果模式有多个组,则这将是元组列表。除非空匹配项接触到另一个匹配项的开头,否则结果中包括空匹配项。

请注意,它说如果存在组,则将返回组匹配项的列表。您在正则表达式末尾拥有的捕获组正在匹配,因此仅返回每个匹配中组的捕获部分。当您使用finditer时,这些信息只是MatchObject对象中的另一个字段。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接