0

同じ形式の複数のファイルを読み取ろうとしており、正規表現に基づいて統計を作成したいと考えています。

つまり、[] 内にある同様のアイテムをカウントしたい

 NC_013618 NC_013633 ([T(nad6 trnE ,cob trnT ,)])
C_013481 NC_013479 ([T(trnP ,rrnS trnF trnV rrnL nad1 trnI ,)])
NC_013485 NC_003159 ([T(trnC ,trnY ,)])
NC_013554 NC_013254 ([T(trnR ,trnN ,)])
NC_013607 NC_013618 ([T(nad6 trnE ,cob trnT ,)])

問題は、私が正しい値を取得していないことです.以下は私のコードです:

 use strict;
 use warnings;

my %data;
@FILES = glob("../mitos-crex/*.out");
foreach my $file (@FILES) {
    local $/ = undef;
    open my $fh, '<', $file;
    $data{$file} = <$fh>;
}

my @t;
my $c = 0;
foreach my $line (keys %data) {
    foreach my $l ($data{$line}) {
         print $l."\n";
        ($t[$c]) = $l =~ m/(\[.*\])/;

        $c++;
    }
}

#the problem is here the counter is not giving the right value

print $c;
my %counts;
$counts{$_}++ for @t;

前もって感謝します

4

2 に答える 2

3

まず、常に use strictuse warnings. この測定は、他の方法では見落としたり、デバッグに時間を浪費したりする可能性のある単純な問題をすばやく明らかにするため、すべてのプログラミングに不可欠です。これは特に当てはまり、自分のプログラムについて他の人に助けを求めている場合の単純な礼儀です。

ファイル全体を単一の文字列に丸呑みすることと、行の配列に丸呑みすることの間で混乱しているようです。あなたが書いた方法では、各要素$data{file}はファイルのすべてのデータを含む単一のスカラー値であり、それをforeach $l ($data{$line}) { ... }一度だけ実行[...]して、ファイル内の最初の文字列のみを見つけようとします。

通常、この方法ですべてのファイル データを読み込むべきではないと思いますが、問題はより良いストリーミング ソリューションを持っている可能性が高いためです。私のソリューションはあなた自身のデザインに従います

データをスカラーではなく仮想配列に丸呑みし、それをループで反復処理する必要があると思います。$/ファイルが行単位で読み取られるように定義したままにして、 で無名配列を作成する必要があります[ <$fh> ]。次に、次の行を反復処理できますforeach my $line (@{ $data{$file} }) { ... }

use strict;
use warnings;

my %data;

my @files = glob("../mitos-crex/*.out");

foreach my $file (@files) {
    open my $fh, '<', $file or die $!;
    $data{$file} = [ <$fh> ];
}

my $c = 0;
my @t;
foreach my $file (keys %data) {
    foreach my $line (@{ $data{$file} }) {
        ($t[$c]) = $line =~ /(\[.*\])/;
        $c++;
    }
}

print $c;
my %counts;
$counts{$_}++ for @t;
于 2012-09-16T19:46:15.080 に答える
0

カウンターは正しい値を示しています。あなたの問題は、ファイルを丸呑みしている(一度にすべてを読み取っている)が、最初に見つかった値のみを保存していることです。

($t[$c]) = $data{$line} =~ m/(\[.*\])/;  # only finds first value in file

各ファイルを適切にループし、各行に上記の正規表現を使用するか、次のようにします。

push @t, ($data{$line} =~ m/(\[.*\])/g);

常に使用する必要があります

use strict;
use warnings;

結果として生じるエラー/警告を解決します。そうしないのは悪い考えであり、コード内の問題を隠しているだけであり、解決していません。

また、次のステートメントにも注意してください。

foreach $l ($data{$line}) {

ここでの各「行」はファイル全体であり、スカラー値以外であるため、 1回だけ反復します。さらに、エイリアスとして$data{$line}使用して反復しますが、ループ内で使用するため、ループが完全に冗長になります。$l$data{$line}

于 2012-09-16T19:30:42.160 に答える