我有一个50mb的正则表达式,我用它来分开短语。
以下是相关代码:
import io
import re
with io.open('REGEXES.rx.txt', encoding='latin-1') as myfile:
regex = myfile.read()
while True == True:
Password = input("Enter a phrase to be split: ")
Words = re.findall(regex, Password)
print(Words)
由于正则表达式如此之大,这需要永远!
这是我现在尝试的代码,使用re.compile(TempRegex):
import io
import re
with io.open('REGEXES.rx.txt', encoding='latin-1') as myfile:
TempRegex = myfile.read()
regex = re.compile(TempRegex)
while True == True:
Password = input("Enter a phrase to be split: ")
Words = re.findall(regex, Password)
print(Words)
我尝试做的是尝试检查输入的词组是否是名称的组合。例如,短语" johnsmith123"返回[' john',' smith',' 123']。正则表达式文件是由来自Facebook的每个名字和姓氏的单词列表中的工具创建的。我想看看输入的短语是否是该单词列表中的单词组合......如果johns和mith是列表中的名字,那么我想要" johnsmith123"返回[' john',' smith',' 123',' johns',' mith']。
答案 0 :(得分:1)
我认为正则表达式不是这里的方式。在我看来,你所要做的就是找到一个恰好是名字的给定字符串的所有子串的列表。
如果用户的输入是密码或密码,则表示字符串相对较短。很容易将该字符串分解为可能的子字符串集,然后针对包含名称的另一个集合测试该字符串。
长度 n 的字符串中的子串数是 n(n + 1)/ 2 。假设没有人输入超过40个字符,你只能看820个子串,其中许多可以被淘汰为太短。以下是一些代码:
def substrings(s, min_length=1):
for start in range(len(s)):
for length in range(min_length, len(s)-start+1):
yield s[start:start+length]
因此,问题是将名称加载到合适的数据结构中。您的正则表达式是50MB,但考虑到您在其中一条评论中显示的片段,由于正则表达式语法的开销,实际数据量将远远小于此值。
如果您只使用每行一个名称的文本文件,则可以执行此操作:
names = set(word.strip().lower() for word in open('names.txt'))
def substrings(s, min_length=1):
for start in range(len(s)):
for length in range(min_length, len(s)-start+1):
yield s[start:start+length]
s = 'johnsmith123'
print(sorted(names.intersection(substrings(s)))
可能会输出:
['jo', 'john', 'johns', 'mi', 'smith']
我怀疑在给定可能的小数据集的情况下会出现内存问题,但是如果您发现没有足够的内存可以立即加载完整的数据集,那么您可以使用sqlite3
和一个简单的表来查看存储名称。查询速度会慢一些,但它会适合内存。
另一种方法是使用shelve
模块创建一个名称为键的持久字典。
答案 1 :(得分:0)
Python的正则表达式引擎实际上并不是正则表达式,因为它包含诸如lookbehind,捕获组,反向引用等功能,并使用回溯来匹配最左边的有效分支而不是最长的分支。
如果你使用真正的正则表达式引擎,如果正则表达式不需要这些功能,你几乎总会得到更好的结果。
真正的正则表达式最重要的特性之一是总是以与输入长度成比例的时间返回结果,而不使用任何内存
我自己编写了一个使用C语言实现的DFA(但可以从python通过cffi使用),它将具有最佳的渐近性能,但我还没有尝试过常量因子改进,例如矢量化和汇编生成。我没有制作一个普遍可用的API,因为我只需要从我的库中调用它,但从示例中找出它应该不难。 (请注意,搜索可以实现为与前面的.*
匹配,然后向后匹配,但出于我的目的,我宁愿将单个字符作为错误令牌返回)。 Link to my project
您也可以考虑离线构建DFA并将其用于程序的多次运行 - 但这是flex
所做的,所以我没有为我的项目做这些,所以也许只是使用它你对C感到满意吗?当然,你几乎肯定要编写一些自定义C代码来使用我的项目......
答案 2 :(得分:-3)
如果编译它,正则表达式模式将被编译成字节码,然后由匹配的引擎运行。如果你不编译它,它会在调用它时反复加载相同的正则表达式。这就是为什么如果你为多个不同的记录使用相同的正则表达式,编译一个更快。