【问题标题】:Find shortest matches between two strings查找两个字符串之间的最短匹配
【发布时间】:2022-01-19 23:34:12
【问题描述】:

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

以下是来自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,接近文件末尾。

【问题讨论】:

  • 好吧,如果你想在startend之间进行匹配,那么你得到start spam作为开始结果是很正常的......你能澄清一下你想要的行为吗?

标签: python regex


【解决方案1】:

这个正则表达式应该匹配你想要的:

(start((?!start).)*?end)

使用re.findall 方法和单行修饰符re.S 获取多行字符串中的所有出现:

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

查看测试here

【讨论】:

【解决方案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”结尾的东西。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-27
    • 2019-03-16
    • 1970-01-01
    相关资源
    最近更新 更多