10

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.in 中有 10000 个查询和近 100000 个原始查询,所以需要很长时间才能完成(比如 5 小时)。是否有快速替代 grep -f 的方法?

4

8 回答 8

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 倍。

于 2012-07-15T07:12:15.607 回答
8

如果您有固定字符串,请使用grep -F -f. 这比正则表达式搜索要快得多。

于 2012-07-15T08:17:50.887 回答
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;
于 2012-07-15T07:07:13.083 回答
4

如果文件已经排序:

join file1 file2

如果不:

join <(sort file1) <(sort file2)
于 2012-07-15T11:01:57.233 回答
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
于 2012-07-15T15:13:27.437 回答
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";
于 2012-07-15T07:18:12.043 回答
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; } 
  }
}
于 2012-07-15T07:26:56.863 回答
0

这可能有点过时,但它是为简单的 UNIX 实用程序量身定制的。鉴于:

  • 键是固定长度的(这里是 7 个字符)
  • 文件已排序(在示例中为 true),允许使用快速合并排序

然后:

$ 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
于 2019-03-14T14:49:07.993 回答