查找两个字符串之间的最短匹配
Posted
技术标签:
【中文标题】查找两个字符串之间的最短匹配【英文标题】:Find shortest matches between two strings 【发布时间】:2022-01-19 23:34:12 【问题描述】:我有一个很大的日志文件,我想在两个字符串之间提取一个多行字符串:start
和 end
。
以下是来自inputfile
的示例:
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,均匀分布 “结束”的出现次数:~800,接近文件末尾。【问题讨论】:
好吧,如果你想在start
和end
之间进行匹配,那么你得到start spam
作为开始结果是很正常的......你能澄清一下你想要的行为吗?
【参考方案1】:
这个正则表达式应该匹配你想要的:
(start((?!start).)*?end)
使用re.findall
方法和单行修饰符re.S
获取多行字符串中的所有出现:
re.findall('(start((?!start).)*?end)', text, re.S)
查看测试here。
【讨论】:
为什么我以前从未听说过 regex101...? 关于 regex101 的好答案和演示。我缺少的关键是消极的前瞻。真的很有用。 也可以在 JS 中工作。 你能解释一下((?!start).)
吗?
@FrancescoBoi 见Tempered Greedy Token - What is different about placing the dot before the negative lookahead。【参考方案2】:
用代码来做——基本状态机:
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 = []
【讨论】:
也完全有效。【参考方案3】:这很棘手,因为默认情况下,re
模块不会查看重叠匹配。较新版本的 Python 有一个新的 regex
模块,允许重叠匹配。
https://pypi.python.org/pypi/regex
你想使用类似的东西
regex.findall(pattern, string, overlapped=True)
如果您坚持使用 Python 2.x 或其他没有 regex
的东西,仍然有可能使用一些技巧。一位才华横溢的人在这里解决了这个问题:
Python regex find all overlapping matches?
一旦你有所有可能的重叠(我想是非贪婪的)匹配,只需确定哪个是最短的,这应该很容易。
【讨论】:
我添加了一些关于日志文件实际大小的信息。在这种情况下,存储所有重叠的匹配项会超出我计算机的磁盘空间。 好吧,我链接到的解决方案返回一个迭代器,因此您实际上不需要存储所有重叠匹配,一次只需要存储一两个。但考虑到您尝试解析的文件格式,接受的解决方案可能更适合您的目的。【参考方案4】:你可以(?s)start.*?(?=end|start)(?:end)?
,然后过滤掉所有不以“end”结尾的东西。
【讨论】:
以上是关于查找两个字符串之间的最短匹配的主要内容,如果未能解决你的问题,请参考以下文章