2012-03-22 12 views
1

私はPerlに戻り、自分のコードで時間を浪費しようとしています。私は大きなソース.DATファイル(2GB)を持っています。私はその.DATファイルで検索したい文字列(それらのほぼ2000)を含む別の.TXTファイルを持っています。その.TXTファイルから配列に値をスローします。巨大なファイルを検索して文字列を検索する効率的な方法は何ですか?

私は、効率的に、アレイ内のこれらの文字列のそれぞれについて、検索、および出力の試合をしたいです。誰も私をまっすぐに助けることができますか?前もって感謝します!もちろん、常に失敗します

if (undef =~ /$array[$x]/) { 

my $source = "/KEYS.txt"; 
my $data= "/claims.dat"; 
my @array; 
my $arraySize = scalar (@DESYarray); 

open (DAT, $data) or die "Cannot open file!"; 
open (LOG, ">>/output.log"); 

open (TXT,$source); 
while (my $searchValues = <TXT>) { 
    push (@array, $searchValues); 
} 
close (TXT); 


while (my $line = <DAT>) {  
for (my $x = 0; $x <= $arraySize; $x++) { 
    if (my $line =~ /$array[$x]/) { 
     print LOG $line; 
    } 
} 
} 

close (DAT); 
close (LOG); 
+2

、あなたはおそらく 'grep'(LINUX/UNIX版ではなく、Perlを)使用することができます。例えば。 'grep -f /KEYS.txt/claims.dat'です。 – TLP

+0

KEYS.txtの文字列が固定されているのか、それとも正規表現ですか?もしそれらが修正されていれば、 'grep -F -f KEYS.txt claims.dat'でスピードアップします。 Perlコードはマッチ演算子の代わりに['index'](http://p3rl.org/index)関数を使用します。 – daxim

+0

KEYS.txtでは、実際には9桁です。他のポスターように102361550と481543095など – cluckinchicken

答えて

1

あなたはそれが等しくなることを意味している、あなたの内側のループでmy $lineを再宣言しています。

Use of uninitialized value in pattern match (m//) at ... 

私はあなたが警告を使用していない疑いがあるになり、非常に悪い考えです:あなたはuse warningsを使用していた場合は、エラーを得ているでしょう。

また、値を@arrayに読み込むと最後に改行が追加されるため、DATファイルで\nで終わる文字列を検索しているため、必要でない可能性があります。例えば。 foo\nの場合は、foo bar bazと一致しません。

それに対する解決策は、あなたのデータをchompすることです:

chomp(my @array = <TXT>); 

はい、あなたは、配列をムシャムシャ食べることができ、あなたは配列に、このようにファイル全体を割り当てることができます。

スクリプトを少し改善することができます。実際に何かのインデックスを使用する必要がない限り、配列インデックスを使用してループするのは非常に不要です。 \Qを使用して

use strict; 
use warnings; # ALWAYS use these! 
use autodie;  # handles the open statements for convenience 

my $source = "/KEYS.txt"; 
my $data= "/claims.dat"; 

open $txt, '<', $source; 
chomp(my @array = <$txt>); 
close $txt; 

open my $dat, '<', $data; # use three argument open and lexical file handle 
open my $log, '>>', "/output.log"; 

while (<$dat>) {   # using $_ for convenience 
    for my $word (@array) { 
     if (/\Q$word/i) { # adding /i modifier to match case insensitively 
      print $log $line; # also adding \Q to match literal strings 
    } 
} 

は、あなたのKEYS.txtファイルが含まれているものに応じて、非常に重要であるかもしれません。正規表現のメタ文字は、文字通り一致すると予想される場合、微妙な不一致を引き起こす可能性があります。例えば。 foo?などの単語がある場合、正規表現/foo?/fooに一致しますが、forにも一致します。

また、部分一致を許可するかどうかを決めることもできます。例えば。 /foo/footballと一致します。

/\b\Q$word\E\b/i 

あなたは\Q .. \Eシーケンス外にそれらを配置する必要があります、または彼らは文字通りに解釈されます。それを克服するために、一つの方法は、単語境界エスケープ文字を使用することです。

ETA: Tchristが指摘しBorodinが示唆するように、すべての単語を含む正規表現を構築すると、重複する行が保存されます。例えば。あなたは言葉"foo""bar""baz"、そしてあなたは、この行が一致する各単語のために一回、3回印刷になるだろうfoo bar bazラインを持っている場合。

これは後で、データを適切な方法で削除することで修正される可能性があります。あなただけがあなたのデータを知っており、これが問題であるかどうかはわかりません。パフォーマンス上の理由から、このような長い正規表現をコンパイルすることを躊躇しますが、それを試して、それがあなたのために働くかどうかを確認することができます。

+1

正規表現をプリコンパイルする必要があります。また、なぜマッチごとに行を印刷するのですか?一致する行だけを出力してください。これは、「... | ... | ... | ...」解決策につながり、これはトライデータ構造に最適化されます。 – tchrist

+0

@tchrist 2000語の正規表現を構築するのが最適ではないので、正規表現が最適です。おそらくperlは、それを良い考え方のように最適化することができます。プリコンパイルすることで – TLP

+0

@tchristは、私はあなたは私が、@ array' '@array =マップQR/\ Q $ _ /のようなものを意味すると仮定しますか?パフォーマンスを向上させるでしょうか? – TLP

1

特に、コードのヘルプを求めている場合は、use strictuse warningsでプログラムを開始してください。彼らはデバッグに大きな助けとなり、しばしば見落とされやすい簡単な間違いを見つけることがあります。

KEYS.txt内の文字列がどのくらいありますか? join '|', @arrayを使ってそれらから正規表現を作ることは実現可能かもしれません。ところで、あなたが書いたコードは@array = <TXT>に相当し、その内容をムシャムシャ食べることを忘れないでください!

私はこの

use strict; 
use warnings; 

my $source = "/KEYS.txt"; 
my $data= "/claims.dat"; 

open my $dat, '<', $data or die "Cannot open data file: $!"; 
open my $log, '>>', '/output.log' or die "Cannot open output file: $!"; 

open my $txt, '<', $source or die "Cannot open keys file: $!"; 
my @keys = <$txt>; 
chomp @keys; 
close $txt; 

my $regex = join '|', map quotemeta, @keys; 
$regex = qr/$regex/i; 

while (my $line = <$dat>) { 
    next unless $line =~ $regex; 
    print $log $line; 
} 

close $log or die "Unable to close log file: $!"; 
0

のようなものを提案し、私は正規表現を使用しました::、トークンのリストを取る最適化された正規表現を作成し、それが大量のテキストをフィルタに使用するために、過去に組み立てます。私たちが| Regexp :: Assembleに区切られた正規表現は、パフォーマンスを大幅に向上させました。この特定の問題については

Regexp::Assemble

+2

これは今自動的に行われます。 http://p3rl.org/perl5100delta#Trie-optimisation-of-literal-string-alternations – daxim

関連する問題