Bash:如何通过两个大文件来优化/并行化搜索以替换字符串?

时间:2014-11-28 04:38:10

标签: bash perl sed parallel-processing fasta

我试图想办法加快模式搜索并替换两个大文本文件(> 10Mb)。 File1有两列,每行都有唯一的名称。 File2有一列包含File1中的一个共享名称,没有特定的顺序,下面有一些文本跨越可变数量的行。他们看起来像这样:

File1:

uniquename1 sharedname1
uqniename2 sharedname2
...

File2:

>sharedname45
dklajfwiffwf
flkewjfjfw
>sharedname196
lkdsjafwijwg
eflkwejfwfwf
weklfjwlflwf

我的目标是使用File1将sharedname变量替换为相应的uniquename,如下所示:

New File2:

>uniquename45
dklajfwif
flkewjfj
>uniquename196
lkdsjafwij
eflkwejf

这是我迄今为止所尝试过的:

while read -r uniquenames sharednames; do
    sed -i "s/$sharednames/$uniquenames/g" $File2
done < $File1

它有效,但它的速度非常慢,在这些大文件中跋涉。 CPU使用率是限速步骤,因此我尝试将修改并行使用我可以使用的8个内核,但无法使其工作。我也尝试将File1和File2分成更小的块并同时批量运行,但我也无法实现这一点。你会如何并行实现这个?或者您是否看到了不同的做法?

欢迎任何建议。

更新1

优秀!感谢@Cyrus和@JJoao以及其他评论员提出的建议。我在我的脚本中实现了两个,在@JJoao的推荐下测试计算时间,它是一个改进(约3小时而不是〜5)。但是,我只是在进行文本文件操作,所以我不知道它应该花费多少时间。所以,我仍然在努力更好地利用可用的CPU,所以我在修改建议,看看能不能进一步加快速度。

更新2:更正为更新1 我将修改包含在我的脚本中并按原样运行,但是我的一大块代码正在减慢它的速度。相反,我在目标中间文件上单独运行建议的代码位。这就是我所看到的:

Time for @Cyrus' sed to complete
real    70m47.484s
user    70m43.304s
sys     0m1.092s

Time for @JJoao's Perl script to complete
real    0m1.769s
user    0m0.572s
sys     0m0.244s

看起来我将使用Perl脚本。感谢大家的帮助!

更新3 这是@ Cyrus&#39;改进的sed命令:

time sed -f <(sed -E 's|(.*) (.*)|s/^\2/>\1/|' File1 | tr "\n" ";") File2
real    21m43.555s
user    21m41.780s
sys     0m1.140s

2 个答案:

答案 0 :(得分:4)

使用GNU sed和bash:

sed -f <(sed -E 's|(.*) (.*)|s/>\2/>\1/|' File1) File2

<强>更新

试图加快速度:

sed -f <(sed -E 's|(.*) (.*)|s/^>\2/>\1/|' File1 | tr "\n" ";") File2

答案 1 :(得分:2)

#!/usr/bin/perl

use strict;
my $file1=shift;
my %dic=();

open(F1,$file1) or die("cant find replcmente file\n");
while(<F1>){                       # slurp File1 to dic
  if(/(.*)\s*(.*)/){$dic{$2}=$1}
}

while(<>){                         # for all File2 lines
  s/(?<=>)(.*)/ $dic{$1} || $1/e;  # sub ">id" by >dic{id}
  print
}

我更喜欢@cyrus解决方案,但如果您需要经常这样做,您可以使用以前的perl脚本(chmod + install)作为 dict-replacement命令。

用法:dict-replacement File1 File* > output

如果你能告诉我们各种解决方案的时间,那就太好了......