为什么re.findall()给我的结果与Python中的re.finditer()不同?

时间:2011-05-27 21:04:36

标签: python regex

我写了这个正则表达式:

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 个答案:

答案 0 :(得分:7)

Findall返回匹配组列表。正则表达式中的parantheses定义了一个可以认为你想要的组,但是你不需要组。 (?:...)是一个非捕获性的paranthesis。将正则表达式更改为:

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

答案 1 :(得分:3)

当你给re.findall()一个带有组(带括号的表达式)的正则表达式时,它会返回匹配的。在这里,你只有一组,而且是|或者]]最后。另一方面,在你使用re.finditer()的代码中,你要求的不是特别的组,所以它给你整个字符串。

你可以让re.findall()通过在整个正则表达式周围加上括号来实现你想做的事情 - 或者只是在你实际想要提取的部分周围。假设您正在尝试解析wiki链接,那将是第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', ']]')]

答案 2 :(得分:1)

我认为findall() documentation的关键位是:

  

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

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

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

finditer()似乎没有任何此类条款。

答案 3 :(得分:1)

他们不会返回相同的东西。来自docs的一些代码段:

  

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

     

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

答案 4 :(得分:0)

来自python文档:

  

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

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