我正在调整此处提出的现有perl脚本: Fast alternative to grep -f
我需要过滤许多非常大的文件(地图文件),每个文件大约1000万行x5个字段宽,使用一个长列表(过滤文件)和匹配的地图文件中的打印行。我尝试使用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 -
我希望输出行看起来像这样,因为它们包含map和filter文件中的字符串。
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"; }
}
答案 0 :(得分:5)
你似乎没有真正尝试过自己解决这个问题。您展示的代码甚至无法编译
有几个原因导致它无效
您正在使用带有隐式控制变量的文件读取循环,这些控制变量将每行读入$_
,但您希望数据能够显示在$lines
和$samlines
中。您还使用了$samline
,但您甚至没有声明
该行
my %keys
最后需要一个分号
我不知道您对$lines
的期望,但是为这样的哈希分配标量值
%keys = $lines;
将在哈希分配中生成警告奇数个元素,并为您留下仅包含单个元素的哈希
这是一个Perl程序,可以执行我认为您的意图,但我不能说它是否会比command_line grep
快得多。请注意,我使用了autodie
pragma而不是显式测试每个文件IO操作的状态
#!/usr/bin/env perl
use strict;
use warnings;
use v5.10.1;
use autodie;
my ($filter_f, $sam_f) = @ARGV;
my %filter;
{
open my $fh, '<', $filter_f;
while ( <$fh> ) {
$filter{$1} = 1 if /(\S+)/;
}
}
open my $fh, '<', $sam_f;
while ( <$fh> ) {
print if /(\S+)/ and $filter{$1};
}
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 +
答案 1 :(得分:0)
因此,鲍罗丁提出的脚本确实有效。但是,我发现我的文件太大而无法完成。相反,我使用&#39; sort&#39;对两个文件进行了排序。然后跟着加入。
join -1 1 -2 1 filter.file map.file > filtered.map
对于48个作业中的每一个,我保留了16G的RAM和8个处理器。
谢谢大家的帮助!