【问题标题】:findall/finditer on a stream?findall/finditer 在流上?
【发布时间】:2012-03-19 11:41:11
【问题描述】:

有没有办法将re.findall 或更好的re.finditer 功能应用于流(即打开文件句柄以供读取)?

请注意,我不是假设要匹配的模式完全包含在一行输入中(即允许多行模式)。我也没有假设最大匹配长度。

确实,在这个通用级别上,可以指定一个要求正则表达式引擎访问整个字符串的正则表达式(例如r'(?sm).*'),当然,这意味着必须将整个文件读入内存,但目前我并不关心这种最坏的情况。毕竟,完全可以编写多行匹配的正则表达式,而 不需要 需要将整个文件读入内存。

是否可以从已编译的正则表达式访问底层自动机(或内部使用的任何东西),为其提供字符流?

谢谢!

编辑:添加了关于多行模式和匹配长度的说明,以回应 Tim Pietzcker 和 rplnt 的回答。

【问题讨论】:

  • 感谢您的编辑 - 我已经更新了我的答案。

标签: python regex stream


【解决方案1】:

如果您知道正则表达式匹配永远不会跨越换行符,这是可能的。

那么你可以简单地做

for line in file:
    result = re.finditer(regex, line)
    # do something...

如果匹配可以扩展到多行,则需要将整个文件读入内存。否则,你怎么知道你的匹配是否已经完成,或者前面的某些内容是否会使匹配变得不可能,或者匹配不成功是因为文件读取得不够远?

编辑:

理论上是可以做到的。正则表达式引擎必须检查在匹配尝试期间的任何时候它是否到达流的当前读取部分的末尾,如果是,则继续读取(可能直到 EOF)。但是 Python 引擎不这样做。

编辑 2:

我查看了 Python 标准库的 re.py 及其相关模块。正则表达式对象的实际生成,包括其.match() 方法和其他方法是在 C 扩展中完成的。因此,除非您直接编辑 C 源代码并构建自己的 Python 版本,否则您无法访问并对其进行猴子补丁处理以处理流。

【讨论】:

    【解决方案2】:

    可以在已知最大长度的正则表达式上实现。没有 +/* 或您知道最大重复次数的那些。如果您知道这一点,您可以逐块读取文件并匹配这些文件,从而产生结果。您还可以在重叠块上运行正则表达式,而不是涵盖正则表达式匹配但在字符串末尾停止的情况。

    一些伪(python)代码:

    overlap_tail = ''
    matched = {}
    for chunk in file.stream(chunk_size):
        # calculate chunk_start
        for result in finditer(match, overlap_tail+chunk):
            if not chunk_start + result.start() in matched:
                yield result
                matched[chunk_start + result.start()] = result
        # delete old results from dict
        overlap_tail = chunk[-max_re_len:]
    

    只是一个想法,但我希望你能得到我想要实现的目标。您需要考虑文件(流)可能会结束以及其他一些情况。但我认为可以做到(如果正则表达式的长度有限(已知))。

    【讨论】:

      猜你喜欢
      • 2011-04-18
      • 1970-01-01
      • 2017-01-18
      • 2014-10-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-21
      相关资源
      最近更新 更多