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明白了。也非常有效。我添加了一些关于日志文件实际大小的信息。在这种情况下,存储所有重叠匹配将超过我计算机的磁盘空间。我链接的解决方案返回一个迭代器,因此实际上不需要存储所有重叠匹配,一次只存储一个或两个。但是考虑到您试图解析的文件的格式,接受的解决方案可能更适合您的目的。