Python 的正则表达式:在边界内查找所有内容

RegEx with Python: findall inside a boundry

我有一个字符串,可以通过以下内容(预期的额外空格)来说明:

"words that don't matter   START    some words one       some words two     some words three   END    words that don't matter"

为了获取 START 和 END ['some words one', some words two', 'some words three'] 之间的每个子字符串,我编写了以下代码:

result = re.search(r'(?<=START).*?(?=END)', string, flags=re.S).group()
result = re.findall(r'(\(?\w+(?:\s\w+)*\)?)', result)

是否可以用一个正则表达式实现这一点?

理论上,您可以将第二个正则表达式包装在 ()* 中,然后将其放入第一个正则表达式中。这将捕获边界内所有出现的内部表达式。不幸的是,Python 实现仅保留多次匹配的组的最后一个匹配项。据我所知,保留组的所有匹配项的唯一实现是 .NET 实现。很遗憾,这不是适合您的解决方案。

另一方面,为什么您不能简单地保留现有的两步法?


编辑: 您可以使用在线正则表达式工具比较我描述的行为。

模式:(\w+\s*)*输入:aaa bbb ccc

例如用 https://pythex.org/ and http://regexstorm.net/tester 试试。 你会看到 Python returns 一个 match/group 是 ccc 而 .NET returns </code> 是三个 <em>captures</em> <code>aaa, bbb, ccc.


Edit2:正如@Jan 所说,还有更新的 regex 模块支持多重捕获。我完全忘记了。

这是我们可以使用 re.split 的理想情况,正如@PeterE 提到的那样,以规避只能访问最后捕获的组的问题。

import re
s=r'"words that don\'t matter   START    some words one       some words two     some words three   END    words that don\'t matter" START abc  a bc c   END'
print('\n'.join(re.split(r'^.*?START\s+|\s+END.*?START\s+|\s+END.*?$|\s{2,}',s)[1:-1]))

启用 re.MULTILINE/re.M 标志,因为我们正在使用 ^$


输出

some words one
some words two
some words three
abc
a bc c

使用较新的 regex 模块,您可以一步完成:

(?:\G(?!\A)|START)\s*\K
(?!\bEND\b)
\w+\s+\w+\s+\w+


这看起来很复杂,但分解后,它说:

(?:\G(?!\A)|START)  # look for START or the end of the last match
\s*\K               # whitespaces, \K "forgets" all characters to the left
(?!\bEND\b)         # neg. lookahead, do not overrun END
\w+\s+\w+\s+\w+     # your original expression


Python 中看起来像:

import regex as re

rx = re.compile(r'''
        (?:\G(?!\A)|START)\s*\K
        (?!\bEND\b)
        \w+\s+\w+\s+\w+''', re.VERBOSE)

string = "words that don't matter   START    some words one       some words two     some words three   END    words that don't matter"

print(rx.findall(string))
# ['some words one', 'some words two', 'some words three']


此外,请参阅 a demo on regex101.com