对于单个大文本(~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之外)也将受到赞赏。
谢谢!
答案 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次搜索和替换操作。使用sed
,awk
或perl
需要数年时间。我无法找到任何执行搜索和替换的Aho-Corasick实现,因此我编写了自己的:fsed。这个工具碰巧是用Python编写的(所以如果你愿意,你可以破解代码),但它被打包成一个命令行实用程序,运行方式类似于sed
。
你可以通过以下方式获得:
pip install fsed
答案 3 :(得分:0)
它们通常只用于搜索字符串,而不是替换它
完美,这正是您所需要的。在4G文本中使用无效算法进行搜索已经够糟糕了,但是进行多次替换可能更糟糕......您可能需要移动千兆字节的文本,以便为源和目标文本的大小差异导致的扩展/收缩腾出空间
找到位置,然后用替换部件连接件。
所以一个愚蠢的比喻是"_".join( "a b c".split(" ") )
,但当然你不想像split
那样创建副本。
注意:在python中执行此操作的任何原因?