在流上找到/找到者?

时间:2012-03-19 11:41:12

标签: python regex stream

有没有办法让re.findall或更好的re.finditer功能应用于流(即文件句柄可供阅读)?

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

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

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

谢谢!

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

2 个答案:

答案 0 :(得分:3)

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

然后你可以简单地做

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

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

修改

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

编辑2:

我看过Python stdlib的re.py及其相关模块。实际生成的正则表达式对象(包括其.match()方法和其他对象)是在C扩展中完成的。因此,除非直接编辑C源并构建自己的Python版本,否则无法访问和monkeypatch它也可以处理流。

答案 1 :(得分:2)

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

一些伪(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:]

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