Python从列表中获取所有regexp匹配组

Python从列表中获取所有regexp匹配组,python,regex,Python,Regex,假设我已经阅读了文本文件的所有行,如下所示: ifile = open('myfile.txt') lines = ifile.readlines() 现在,假设我有以下正则表达式: rgx = re.compile(r'Found ([0-9]+) solutions') 我可以用 result = filter(rgx.match,lines) print result 获取匹配列表,但我需要的是匹配组列表。例如,与以下输出不同: Found 3 solutions Found 35

假设我已经阅读了文本文件的所有行,如下所示:

ifile = open('myfile.txt')
lines = ifile.readlines()
现在,假设我有以下正则表达式:

rgx = re.compile(r'Found ([0-9]+) solutions')
我可以用

result = filter(rgx.match,lines)
print result
获取匹配列表,但我需要的是匹配组列表。例如,与以下输出不同:

Found 3 solutions
Found 35 solutions
Found 0 solutions
3
35
0
我希望输出像:

Found 3 solutions
Found 35 solutions
Found 0 solutions
3
35
0

如何执行此操作?

由于前缀和后缀是固定字符串,因此您可以使用环视:

r'(?<=Found )\d+(?= solutions)'
r'(?您从match命令返回“match”对象(除非您使用filter将其隐式转换为字符串),唉。通过.ipython帮助没有合适的文档,但它是联机的:

例如

内部循环,
(rgx.match(line)表示f中的行)
是一个生成器表达式,其作用类似于
apply()
。对于文件中的每一行,它调用
rgx.match()
,并生成结果,即
SRE_match
对象(我通常称之为“匹配对象”)


外部循环具有
如果m
则丢弃任何不计算为true的结果(
re.match()
当模式不匹配时返回
None
),然后
m.group(1)
使用match对象从括号内获取文本。有关详细信息,请参阅
re
模块的文档。由于外部循环是列表理解的一部分,因此会生成并返回一个结果列表。

因此,此处提供的其他解决方案很好,可能是可读性最高的,但在特定示例中考虑到您的需求,我建议您提供两种单线方案(当然要记住,您的问题来自2013年,您可能不在同一家公司工作,更不用说在同一个项目上工作了)。如果有人发现自己在这里,我也认为这是一个普遍的问题。因为您的前提非常简单(每行有一条有趣的数据),您可以执行以下操作:

>>> # simulate reading the (hopefully not ginormous) file into a single string
>>> lines = "Found 3 solutions\nFound 35 solutions\nFound 0 solutions\n"
>>> # we're now in the state we would be after "lines = file.readlines()"
>>> print(lines)
Found 3 solutions
Found 35 solutions
Found 0 solutions

>>> # we're so constrained, we can get away with murder in a single line
>>> solution_counts = re.findall(r'\d+', file_contents)
>>> solution_counts
['3', '35', '0']
>>> # bazinga!
这是一个令人惊讶的强大解决方案。如果文件的本地化方式将单词“find”和“solutions”更改为翻译后的等效词,则只要格式保持不变,此解决方案就无关紧要。不包含十进制整数的页眉和页脚?无关紧要。它可以处理单个字符串,如
找到计数为3、35和0的解决方案集“完全相同的代码将提取您想要的答案。然而,更常见的是您知道格式,但不能控制它,并且每一行/记录都充满了异构数据,并且您关心的部分被其他人包围,您可能会或可能不关心。因此,请考虑下面古怪的变体:

file_contents = "99 bottles of beer on the wall\n" \
                "50 ways to leave your lover\n" \
                "6 kinds of scary\n" \
                "Found 3 solutions of type A\n" \
                "Found 35 solutions of type C\n" \
                "Found 4 solutions of unknown type\n" \
                "2 heads are better than 1\n" \
                "etc, ...\n"
我们的简单解决方案将返回
['99','50','6','3','35','4','2','1']
,除非你知道如何过滤掉无关的数据,否则就没有那么有趣了,因为这些数据非常混乱、容易出错且脆弱——五分之一是星星。这很简单,而且可能是一个很好的干净解决方案,涉及迭代行,而不是将整个字节流摄入内存,但让我们坚持这样的假设,即出于某种原因,必须这样做。可能它不是来自文件(从TCPIP流或其他任何文件捕获)。使用另一个单行程序,
lines.split('\n')
,我们再次将行分开(没有换行符),并可以进行迭代和理解等,但我们也可以使用
finditer

>>> [ m.group(1) for m in re.finditer(r'Found (\d+)', file_contents) ]
>>> ['3', '35', '4']

非常健壮。我甚至不确定预编译是否更快,除非你正在处理大量的噩梦文件。

谢谢。以前从未使用过lookahead或lookaround。啊,我明白了。我花了一分钟才注意到,你在内部循环中使用了字母“l”而不是数字“1”,但它对我来说非常有效!:)…当然,数字“1”没有任何意义,所以对我来说应该是显而易见的。有一件事太简单了!我编辑了答案,并将变量名从
l
更改为
line
。这应该更清楚了!抱歉。
>>> [ m.group(1) for m in re.finditer(r'Found (\d+)', file_contents) ]
>>> ['3', '35', '4']