有没有办法在python中的流上使用正则表达式匹配? 像
reg = re.compile(r'\w+')
reg.match(StringIO.StringIO('aa aaa aa'))
我不想通过获取整个字符串的值来做到这一点。我想知道是否有任何方法可以匹配srtream上的正则表达式(即时)。
答案 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
传递给re
,partial=True
,regex.match
或regex.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())