我写了这个正则表达式:
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相同的结果?
答案 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对象中的另一个字段。