Python正则表达式解析流

时间:2011-01-08 14:41:14

标签: python regex stream

有没有办法在python中的流上使用正则表达式匹配? 像

reg = re.compile(r'\w+')
reg.match(StringIO.StringIO('aa aaa aa'))

我不想通过获取整个字符串的值来做到这一点。我想知道是否有任何方法可以匹配srtream上的正则表达式(即时)。

4 个答案:

答案 0 :(得分:16)

我遇到了同样的问题。第一个想法是实现一个LazyString类,它就像一个字符串,但只读取当前需要的流中的数据(我通过重新实现__getitem____iter__来获取和缓冲字符到访问的最高位置...)。

这没有用(我从re.match得到了一个“TypeError:期望的字符串或缓冲区”),所以我看了一下标准库中re模块的实现。

不幸的是,在流上使用正则表达式似乎是不可能的。模块的核心是用C实现的,这个实现期望整个输入同时在内存中(我猜主要是因为性能原因)。似乎没有简单的方法可以解决这个问题。

我还看了PYL(Python LEX / YACC),但他们的词法分子在内部使用re,所以这不能解决问题。

可能使用支持Python后端的ANTLR。它使用纯python代码构造词法分析器,似乎能够在输入流上运行。因为对我来说问题并不那么重要(我不希望我的输入变得非常大......),我可能不会进一步调查,但可能值得一看。

答案 1 :(得分:5)

在文件的特定情况下,如果您可以使用mmap对文件进行内存映射,并且如果您使用的是字节串而不是Unicode,则可以将内存映射文件提供给{{1}好像它是一个字节串,它只是工作。这受到地址空间的限制,而不受RAM的限制,因此具有8 GB RAM的64位计算机可以内存映射32 GB文件。

如果你能做到这一点,这是一个非常好的选择。如果你做不到,你必须转向更混乱的选择。

第三方regex模块(不是re)提供部分匹配支持,可用于构建流媒体支持......但它很混乱且有很多警告。像lookbehinds和re这样的东西是行不通的,零宽度匹配对于做对是很棘手,我不知道它是否与其他高级功能^提供和{{ 1}}没有。尽管如此,它似乎是最完整的解决方案。

如果您将regex传递给repartial=Trueregex.matchregex.fullmatch,那么除了报告完整匹配项外,regex.search如果扩展数据,还会报告可能匹配的内容:

regex.finditer

如果有更多数据可以更改匹配结果,它会报告部分匹配而不是完全匹配,因此,例如,regex将始终是部分匹配。

通过这种方式,您可以保持数据的滑动窗口匹配,当您点击窗口结束并从头开始丢弃消耗的数据时,可以将其扩展。不幸的是,任何因数据从字符串开头消失而感到困惑的东西都不会起作用,所以看不见,In [10]: regex.search(r'1234', '12', partial=True) Out[10]: <regex.Match object; span=(0, 2), match='12', partial=True> regex.search(r'[\s\S]*', anything, partial=True)^。零宽度匹配也需要小心处理。以下是在文件或类文件对象上使用滑动窗口的概念验证:

\b

答案 2 :(得分:2)

这似乎是一个老问题。当我发布到a similar question时,您可能希望子类化我的解决方案streamsearch-py的Matcher类并在缓冲区中执行正则表达式匹配。查看kmp_example.py以获取模板。如果事实证明经典的Knuth-Morris-Pratt匹配就是您所需要的,那么现在使用这个小型开源库可以解决您的问题: - )

答案 3 :(得分:-5)

是 - 使用getvalue方法:

import cStringIO
import re

data = cStringIO.StringIO("some text")
regex = re.compile(r"\w+")
regex.match(data.getvalue())