10

file.contain.query.txt

ENST001

ENST002

ENST003

file.to.search.in.txt

ENST001  90

ENST002  80

ENST004  50

ENST003には2番目のファイルにエントリがなく、ENST004には1番目のファイルにエントリがないため、期待される出力は次のとおりです。

ENST001 90

ENST002 80

特定のファイルでマルチクエリをgrepするには、通常、次のようにします。

grep -f file.contain.query <file.to.search.in >output.file

file.to.search.inに10000クエリとほぼ100000rawが含まれているので、完了するまでに非常に長い時間がかかります(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以降を使用している場合は、「パイプ」で区切られたクエリ用語を使用して、「クエリ」用語を正規表現に結合できます。(Like ENST001|ENST002|ENST003:) Perlは、ハッシュのように一定時間でルックアップを行う「トライ」を構築します。ルックアップハッシュを使用したソリューションと同じ速度で実行する必要があります。これを行う別の方法を示すためだけに。

#!/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 に答える