file.contain.query.txt
ENST001
ENST002
ENST003
file.to.search.in.txt
ENST001 90
ENST002 80
ENST004 50
因为ENST003在第二个文件中没有条目而且ENST004在第一个文件中没有条目,所以预期的输出是:
ENST001 90
ENST002 80
要在特定文件中grep多查询,我们通常会执行以下操作:
grep -f file.contain.query <file.to.search.in >output.file
因为我在file.to.search中有10000个查询和几乎100000个raw.in需要很长时间才能完成(比如5个小时)。是否有快速替代grep -f?
答案 0 :(得分:11)
如果您需要纯Perl选项,请将查询文件密钥读入哈希表,然后根据这些密钥检查标准输入:
#!/usr/bin/env perl
use strict;
use warnings;
# build hash table of keys
my $keyring;
open KEYS, "< file.contain.query.txt";
while (<KEYS>) {
chomp $_;
$keyring->{$_} = 1;
}
close KEYS;
# look up key from each line of standard input
while (<STDIN>) {
chomp $_;
my ($key, $value) = split("\t", $_); # assuming search file is tab-delimited; replace delimiter as needed
if (defined $keyring->{$key}) { print "$_\n"; }
}
你会这样使用它:
lookup.pl < file.to.search.txt
哈希表可以占用大量内存,但搜索速度要快得多(哈希表查找处于恒定时间内),这很方便,因为您查找的密钥比存储密钥多10倍。
答案 1 :(得分:6)
如果您有固定字符串,请使用grep -F -f
。这比正则表达式搜索要快得多。
答案 2 :(得分:5)
此Perl代码可以帮助您:
use strict;
open my $file1, "<", "file.contain.query.txt" or die $!;
open my $file2, "<", "file.to.search.in.txt" or die $!;
my %KEYS = ();
# Hash %KEYS marks the filtered keys by "file.contain.query.txt" file
while(my $line=<$file1>) {
chomp $line;
$KEYS{$line} = 1;
}
while(my $line=<$file2>) {
if( $line =~ /(\w+)\s+(\d+)/ ) {
print "$1 $2\n" if $KEYS{$1};
}
}
close $file1;
close $file2;
答案 3 :(得分:4)
如果文件已经排序:
join file1 file2
如果不是:
join <(sort file1) <(sort file2)
答案 4 :(得分:4)
如果您使用的是perl版本5.10或更高版本,则可以将“查询”术语加入正则表达式,查询术语由“管道”分隔。 (比如:ENST001|ENST002|ENST003
)Perl构建了一个'trie',它像哈希一样,在恒定时间内进行查找。它应该使用查找散列以与解决方案一样快的速度运行。只是为了表明另一种方法。
#!/usr/bin/perl
use strict;
use warnings;
use Inline::Files;
my $query = join "|", map {chomp; $_} <QUERY>;
while (<RAW>) {
print if /^(?:$query)\s/;
}
__QUERY__
ENST001
ENST002
ENST003
__RAW__
ENST001 90
ENST002 80
ENST004 50
答案 5 :(得分:1)
MySQL的:
将数据导入Mysql或类似内容将提供巨大的改进。这可行吗?你可以在几秒钟内看到结果。
mysql -e 'select search.* from search join contains using (keyword)' > outfile.txt
# but first you need to create the tables like this (only once off)
create table contains (
keyword varchar(255)
, primary key (keyword)
);
create table search (
keyword varchar(255)
,num bigint
,key (keyword)
);
# and load the data in:
load data infile 'file.contain.query.txt'
into table contains fields terminated by "add column separator here";
load data infile 'file.to.search.in.txt'
into table search fields terminated by "add column separator here";
答案 6 :(得分:0)
use strict;
use warings;
system("sort file.contain.query.txt > qsorted.txt");
system("sort file.to.search.in.txt > dsorted.txt");
open (QFILE, "<qsorted.txt") or die();
open (DFILE, "<dsorted.txt") or die();
while (my $qline = <QFILE>) {
my ($queryid) = ($qline =~ /ENST(\d+)/);
while (my $dline = <DFILE>) {
my ($dataid) = ($dline =~ /ENST(\d+)/);
if ($dataid == $queryid) { print $qline; }
elsif ($dataid > $queryid) { break; }
}
}
答案 7 :(得分:0)
这可能有点过时,但是是为简单的UNIX实用程序量身定制的。鉴于:
然后:
$ sort -m file.contain.query.txt file.to.search.in.txt | tac | uniq -d -w7
ENST002 80
ENST001 90
变量:
要去除键后打印的数字,请删除tac命令:
$ sort -m file.contain.query.txt file.to.search.in.txt | uniq -d -w7
要保持排序顺序,请在末尾添加一个额外的tac命令:
$ sort -m file.contain.query.txt file.to.search.in.txt | tac | uniq -d -w7 | tac