【发布时间】:2026-01-28 20:15:01
【问题描述】:
我正在调整此处提出的现有 perl 脚本: Fast alternative to grep -f
我需要过滤许多非常大的文件(地图文件),每个约 1000 万行长 x 5 个字段宽,使用一个同样长的列表(过滤文件)并在地图文件中打印匹配的行。我尝试使用 grep -f,但它只是花费了太长时间。我读到这种方法会更快。
这是我的文件的样子:
过滤文件:
DB775P1:276:C2R0WACXX:2:1101:10000:77052
DB775P1:276:C2R0WACXX:2:1101:10003:51920
DB775P1:276:C2R0WACXX:2:1101:10004:36433
DB775P1:276:C2R0WACXX:2:1101:10004:57256
地图文件:
DB775P1:276:C2R0WACXX:2:1101:10000:70401 chr5 21985760 21985780 -
DB775P1:276:C2R0WACXX:2:1101:10000:77052 chr18 14723904 14723924 -
DB775P1:276:C2R0WACXX:2:1101:10000:77052 chr18 14745586 14745606 -
DB775P1:276:C2R0WACXX:2:1101:10000:77052 chr4 7944241 7944261 -
DB775P1:276:C2R0WACXX:2:1101:10000:77052 chr4 8402856 8402876 +
DB775P1:276:C2R0WACXX:2:1101:10000:77052 chr8 10864708 10864728 +
DB775P1:276:C2R0WACXX:2:1101:10002:88487 chr17 5681227 5681249 -
DB775P1:276:C2R0WACXX:2:1101:10004:74842 chr13 2569168 2569185 +
DB775P1:276:C2R0WACXX:2:1101:10004:74842 chr14 13253418 13253435 -
DB775P1:276:C2R0WACXX:2:1101:10004:74842 chr14 13266344 13266361 -
我希望输出行看起来像这样,因为它们包含地图和过滤器文件中存在的字符串。
DB775P1:276:C2R0WACXX:2:1101:10000:77052 chr18 14723904 14723924 -
DB775P1:276:C2R0WACXX:2:1101:10000:77052 chr18 14745586 14745606 -
DB775P1:276:C2R0WACXX:2:1101:10000:77052 chr4 7944241 7944261 -
DB775P1:276:C2R0WACXX:2:1101:10000:77052 chr4 8402856 8402876 +
DB775P1:276:C2R0WACXX:2:1101:10000:77052 chr8 10864708 10864728 +
这是我迄今为止编辑的脚本,但没有运气:
#!/usr/bin/env perl
use strict;
use warnings;
# Load the files
my $filter = $ARGV[0];
my $sam = $ARGV[1];
open FILE1, $filter;
if (! open FILE1, $filter) {die "Can't open filterfile: $!";}
open FILE2, $sam;
if (! open FILE2, $sam) {die "Can't open samfile: $!";}
# build hash of keys using lines from the filter file
my $lines;
my %keys
while (<FILE1>) {
chomp $lines;
%keys = $lines;
}
close FILE1;
# look up keys in the map file, if match, print line in the map file.
my $samlines;
while (<FILE2>) {
chomp $samlines;
my ($id, $chr, $start, $stop, $strand) = split /\t/, $samline;
if (defined $lines->{$id}) { print "$samline \n"; }
}
【问题讨论】:
-
grepis absurdly fast。也许你可以更快地写一些东西,但最终你仍然是从磁盘线性读取东西。相反,我会考虑将数据放入数据库中。 -
是的,通常我使用 grep -f 来完成类似的任务。事实上,我一直在运行它,同时尝试解决运行速度更快的问题。然而,24 小时后, grep -f 仍然没有完成手头的工作之一。试图做出可敬的尝试,以更快地提出一些建议。
-
将其放入数据库并在那里进行查询可能会更快。 (另外,好名字)我建议您尝试这种方法与您自己的方法并行。
-
文件 IO 的限制因素几乎总是文件 IO。使用什么工具并不重要 - 磁盘旋转得如此之快。优化可能是可行的,例如将文件预加载到内存/数据库/更快的磁盘中。