在Python中快速多次搜索和替换

时间:2013-09-05 20:47:02

标签: python regex search replace

对于单个大文本(~4GB),我需要搜索~1百万个短语并用互补短语替换它们。原始文本和替换都可以轻松地适应内存。天真的解决方案将需要数年时间才能完成,因为单个替换需要大约一分钟。

天真的解决方案:

for search, replace in replacements.iteritems():
    text = text.replace(search, replace)

使用re.sub的正则表达式方法慢了x10:

for search, replace in replacements.iteritems():
    text = re.sub(search, replace, text)

无论如何,这似乎是一个使用Boyer-Moore字符串或Aho-Corasick的好地方;但是这些方法通常只能用于搜索字符串,而不能替换它。

或者,任何可以快速完成此任务的工具(在Python之外)也将受到赞赏。

谢谢!

4 个答案:

答案 0 :(得分:1)

在python之外,sed通常用于此类事情。

例如(取自here),在sue.txt文件中用美丽替换丑陋的单词:

sed -i 's/ugly/beautiful/g' /home/bruno/old-friends/sue.txt

您尚未发布任何代码分析,您应该在进行任何过早优化之前尝试一些时间。搜索和替换4GB文件中的文本是一项计算密集型操作。

<强> ALTERNATIVE 问:我应该这样做吗? -

您在下面讨论在10毫秒内完成整个搜索和替换维基百科语料库。这会敲响一些警钟,因为它听起来不像很棒的设计。除非有明显的理由不应该修改您用于呈现和/或加载的任何代码以进行搜索和替换,因为正在加载/查看数据的子集。您不太可能对整个4GB数据进行多次操作,因此将搜索和替换操作限制为您实际工作的内容。此外,您的时间仍然非常不精确,因为您不知道您正在处理的文件有多大。

最后一点,请注意:

  
    
      

加速必须是算法而不是链接数百万个sed调用

    
  

但是你表示你正在使用的数据是“单个大文本(~4GB)”,所以如果我理解你的意思,就不应该涉及任何转换。

<强>更新 下面你指出要对~4KB文件(我假设)进行操作需要90秒,这对我来说似乎很奇怪 - sed操作通常不需要接近那个。如果文件实际上是4MB(我希望)那么它需要24小时来评估(不理想,但可能接受?)

答案 1 :(得分:1)

可能有一个比这更好的方法:

re.sub('|'.join(replacements), lambda match: replacements[match.group()], text)

这会进行一次搜索,但这不是一次非常有效的搜索。 re2模块可能会大大提高速度。

答案 2 :(得分:1)

我也有这个用例,我需要在维基百科的全文中进行~100,000次搜索和替换操作。使用sedawkperl需要数年时间。我无法找到任何执行搜索和替换的Aho-Corasick实现,因此我编写了自己的:fsed。这个工具碰巧是用Python编写的(所以如果你愿意,你可以破解代码),但它被打包成一个命令行实用程序,运行方式类似于sed

你可以通过以下方式获得:

pip install fsed

答案 3 :(得分:0)

  

它们通常只用于搜索字符串,而不是替换它

完美,这正是您所需要的。在4G文本中使用无效算法进行搜索已经够糟糕了,但是进行多次替换可能更糟糕......您可能需要移动千兆字节的文本,以便为源和目标文本的大小差异导致的扩展/收缩腾出空间

找到位置,然后用替换部件连接件。

所以一个愚蠢的比喻是"_".join( "a b c".split(" ") ),但当然你不想像split那样创建副本。

注意:在python中执行此操作的任何原因?