用于数千个单词的Python正则表达式

3 投票
5 回答
1409 浏览
提问于 2025-04-16 19:09

我正在用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的风格...

撰写回答