快速替换非常大的文件中的文本


25

我有25GB的文本文件,只需要在几行上替换一个字符串即可。我可以sed成功使用,但是运行需要很长时间。

sed -i 's|old text|new text|g' gigantic_file.sql

有更快的方法吗?


您知道要替换的文本所在的行号吗?如果不是,那么加快速度的唯一选择就是获得更快的计算机。您拥有大量数据的事实意味着搜索将花费大量时间。
大卫·金

我可以很快找到行号,所以是的。
eisaacson

您还可以使用多个CPU内核来加快速度-rankfocus.com/use-cpu-cores-linux-commands
ahaswer

不要将sed用于大文件。看一下vi或vim
MikeJRamsey56

Answers:


26

你可以试试:

sed -i '/old text/ s//new text/g' gigantic_file.sql

从这个参考

速度的优化:如果需要提高执行速度(由于输入文件较大或处理器或硬盘速度慢),如果在给出“ s /.../”之前指定了“查找”表达式,则替换将更快地执行。 ../“指令。

这是对10G文件的比较。之前:

$ time sed -i 's/original/ketan/g' wiki10gb
real    5m14.823s
user    1m42.732s
sys     1m51.123s

后:

$ time sed -i '/ketan/ s//original/g' wiki10gb
real    4m33.141s
user    1m20.940s
sys     1m44.451s

最后一个sed拼写错误。我昨天编辑了这篇文章,以修复sed应该为time sed -i '/original/ s//ketan/g' wiki10gbnot 的最后一个命令time sed -i '/ketan/ s//original/g' wiki10gb。我今天要恢复编辑,因为1.时间不再与命令匹配,并且2.我对3+ GB文件上的GNU sed执行了相同的测试,并且我没有观察到两种sed选择之间的任何区别。我怀疑时间的差异是由于拼写错误造成的。
xhienne

@xhienne我不确定您拼写错误是什么意思。在第一轮中,我用“ ketan”替换“原始”一词,在第二轮中,用“ original”替换“ ketan”一词,导致两种情况下的替换次数相等。
mkc

1
我正在应用信誉不足的新用户报告的“修复”。现在我明白了你的所作所为。但是,如果要证明一种语法优于另一种语法,则必须执行完全相同的操作,而在这里不是这样(在CPU方面,查找5个字符的字符串与查找a字符不同) 7个字符的字符串)。此外,对10GB文件的这种测试在很大程度上取决于您的计算机负载(CPU,磁盘)。我个人看到结果有很多波动time,但总的来说,时间没有差异。
xhienne

我相信这是相关的-请在此处查看已接受的答案stackoverflow.com/questions/11145270/… >> sed将整个文件流化,但是如该答案所述,指定行号(如果知道)会有所帮助:就我而言,执行速度提高约2倍(GNU sed 4.5)。您可以根据模式搜索,使用grep -n或ripgrep(rg)查找行号。实际上,根据以上答案,指定行号就像在该文件上有搜索结果。
维多利亚·斯图尔特

1

简短的答案是“否”-您对此类操作的限制因素是磁盘IO。无法更快地传输25GB的磁盘。如果您不进行编辑,则可能会获得较小的改进,并且将的结果写入sed单独的驱动器(如果有可用的话)-因为这样您就可以从一个驱动器读取数据,同时写入另一个驱动器,并且结果减少了争用。

可能可以通过不为每行使用regex引擎来加快速度-例如,使用perl(我很确定您可以使用它,sed但我不知道语法)-这将从10,000行以上。

perl -pe '$. > 10_000 && s/old_text/new_text/g' 

而且,如果RE(元字符)中存在任何复杂的问题,那么将其最小化将略微提高正则表达式引擎的效率。


1
在sed中应该是sed -i '10000,$ s/old_text/new_text/g'
Dani_l

可爱。我不知道如何sed比较-我认为速度稍快,但由于文件大小而并不多。
Sobrique '16

我认为perl比sed快,但是sed的神秘性稍差,或者说它需要的初始学习曲线更少。
Dani_l

1
瞧,现在我反过来说了-您可以(几乎)编写sedin perl,但是后者也可以让您编写更多详细的脚本。
Sobrique '16

0

如果新文本和旧文本的长度相同,则可以查找文件并仅写入更改的字节,而不用复制整个文件。否则,您将陷入移动大量数据的困境。

注意:这很棘手,涉及编写自定义代码。

如果您使用的是C或C ++,请参见手册页中的fseek,或者使用喜欢的语言包装进行搜索和编写系统调用。

如果您仅坚持使用命令行,并且可以获得文本的字节偏移,则可以使用精心编写的“ dd”命令将替换文本写到位。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.