Python 查找两个字符串之间的最短匹配

Python 查找两个字符串之间的最短匹配,python,regex,Python,Regex,我有一个很大的日志文件,我想在两个字符串之间提取一个多行字符串:start和end 以下是输入文件中的示例: start spam start rubbish start wait for it... profit! here end start garbage start second match win. end 所需的解决方案应打印: start wait for it... profit! here end start second match win. end 我尝

我有一个很大的日志文件,我想在两个字符串之间提取一个多行字符串:
start
end

以下是
输入文件
中的示例:

start spam
start rubbish
start wait for it...
    profit!
here end
start garbage
start second match
win. end
所需的解决方案应打印:

start wait for it...
    profit!
here end
start second match
win. end
我尝试了一个简单的正则表达式,但它返回了
start spam
中的所有内容。如何做到这一点

编辑:关于真实计算复杂性的其他信息

  • 实际文件大小:2GB
  • “起始点”的位置:~12 M,均匀分布
  • “end”的出现次数:~800,在文件末尾附近

这很难做到,因为默认情况下,
re
模块不会查看重叠匹配。较新版本的Python有一个新的
regex
模块,允许重叠匹配

你会想用像这样的东西

regex.findall(pattern, string, overlapped=True)
如果你坚持使用Python2.x或者其他没有
regex
的东西,通过一些技巧还是有可能的。一位才华横溢的人在这里解决了这个问题:


一旦您有了所有可能的重叠(我想是非贪婪)匹配,只需确定哪一个最短,这应该很容易。

此正则表达式应该匹配您想要的:

(start((?!start).)*?end)
使用
re.findall
方法和单行修饰符
re.S
获取多行字符串中的所有出现:

re.findall('(start((?!start).)*?end)', text, re.S)

查看测试。

您可以执行
(?s)start.*(?=end | start)(?:end)?
,然后过滤掉所有未以“end”结尾的内容。

使用代码-基本状态机执行此操作:

open = False
tmp = []
for ln in fi:
    if 'start' in ln:
        if open:
            tmp = []
        else:
            open = True

    if open:
        tmp.append(ln)

    if 'end' in ln:
        open = False
        for x in tmp:
            print x
        tmp = []

好吧,如果你想在
start
end
之间匹配,那么你得到
start spam
作为开始结果是正常的。。。你能澄清一下你想要的行为吗?为什么我以前从来没有听说过regex101…?regex101上的好答案和演示。我错过的关键是消极的前瞻。非常有用。也可以用JS。你能解释一下
((?!start)。
?@FrancescoBoi明白了。也非常有效。我添加了一些关于日志文件实际大小的信息。在这种情况下,存储所有重叠匹配将超过我计算机的磁盘空间。我链接的解决方案返回一个迭代器,因此实际上不需要存储所有重叠匹配,一次只存储一个或两个。但是考虑到您试图解析的文件的格式,接受的解决方案可能更适合您的目的。