用于数千个单词的Python正则表达式
我正在用Python在一个字符串中查找特定的关键词。这个字符串大概是这样的:
A was changed from B to C
我想要找到的是“to C”这一部分,其中C是成千上万的单词之一。
这段代码用来构建正则表达式字符串:
pre_pad = 'to '
regex_string = None
for i in words:
if regex_string == None:
regex_string = '\\b%s%s(?!-)(?!_)\\b' %(pre_pad, i)
else:
regex_string = regex_string + '|\\b%s%s(?!-)(?!_)\\b' %(pre_pad, i)
然后我会这样做:
matches = []
for match in re.finditer(r"%s" %regex_string, text):
matches.append([match, MATCH_TYPE])
这段代码在Linux上运行正常,但在macOS上会崩溃,出现“渲染时捕获到溢出错误:正则表达式代码大小限制超出”的错误。
我意识到,regex_string非常长,这就是问题的根源。
print regex_string.__len__()
63574
我该如何解决这个问题,以确保无论单词数量多少都能正常工作呢?
补充说明:
我忘了提到,pre_pad有时是空的:pre_pad = '',所以并不总是能先搜索pre_pad。
另外,我之所以先构建整个regex_string,然后再和单词匹配,是因为我需要对成千上万的条目进行匹配。如果每次都要重新构建regex_string,那样会导致性能非常差。
哦,还有,我需要知道哪个单词匹配上了。
5 个回答
1
老实说,我会用一种稍微不同的方法来解决这个问题。我会先创建一个单词映射表,这样我就可以用O(1)的复杂度来检查某个单词是否存在。接着,我会在大文本中搜索所有符合“to [\w]+”这个正则表达式的内容,也就是找出所有“to”后面跟着的单词。然后,对于每一个找到的匹配项,我会检查它是否在单词映射表中。这样做效率会高很多,我想。
1
你可以通过一个简单的正则表达式从你的输入中提取出C,然后在一个优化过的结构中查找它:
- 某种树形结构
- 使用二分查找的有序列表
- 哈希结构(像Python中的
set
)
类似于下面的代码:
return match_from_regex in set_of_words
4
这不是一个你可以用复杂的正则表达式来解决的任务,也别指望这样能有更好的性能:
pre_pad = 'to '
matches = []
for i in words:
regex_string = '\\b%s%s(?!-)(?!_)\\b' % (pre_pad, i)
for match in re.finditer(r"%s" % regex_string, text):
matches.append([match, MATCH_TYPE])
另外,如果你在分析代码后发现多个正则表达式连在一起运行得更快,那在构建正则表达式的时候,记得计算一下它的长度,并把整个任务分成2、3、10个小部分来处理,以避免出现溢出的问题。
附言:
print len(regex_string)
这样写更符合Python的风格...