-1

大きなテキスト ファイル (コードの前の行で自分で作成したもの) を読み取って解析し、最終的に別のファイルに出力する必要があるため、Perl のバッファリングの問題が発生していると思います。

ある時点で、90,855 行のファイルと 2 番目のファイルの他のファイルを読み取った後、スクリプトはファイルの行を完全に読み取っていません。

これが発生するまでに読み取られた文字数を数えたところ、233,467 文字だったので、ファイルの次の行を読み取る前にバッファをフラッシュしてスリープさせようとしました。うまくいきません。

何か提案はありますか?

これが私のコードです:

foreach $i (@files) {

    my $buff = 0;

    print "Analyzing $i\n";
    sleep(1);
    $program = $1 if $i =~ /(\w+)_SITES/;

    open(FIL, $i) or die "$!: $i\n";
    while (<FIL>) {

        $buff += length($_);
        if ($buff >= 230000) {  #FLUSH THE BUFFER, NOT WORKING!!!
            $buff = 0;
            sleep(1);
            select((select(FIL), $| = 1)[0]);
        }

        undef($a);
        unless ($. == 1) {
            if ($o == 0) {
                if (/^\d+\t(\S+)\t(\S+)\t(\d+)\t(\d+)\t(\S+)\t(\S+)\t(.*)/) {
                    $mirna  = $1;
                    $target = $2;
                    $start  = $3;
                    $end    = $4;
                    $site   = $5;
                    $comp_p = $6;
                    $a      = $7;
                    $j      = "${mirna}_${target}_${start}_$end";
                    $site_nu{$j} = "$mirna\t$target\t$start\t$end\t$site\t$comp_p";    # Store each site in a hash
                }
                else {   #DIES HERE!!!
                  die "$buff characters, in line $.:$_\n"
                }
            }
            else {
                if (/^\d+\t(\S+)\t(\S+)\t(\d+)\t(\d+)\t(\S+)\t(.*)/) {
                    $mirna       = $1;
                    $target      = $2;
                    $start       = $3;
                    $end         = $4;
                    $site        = $5;
                    $a           = $6;
                    $j           = "${mirna}_${target}_${start}_$end";
                    $site_nu{$j} = "$mirna\t$target\t$start\t$end\t$site";    # Store each site in a hash
                }
            }

「DIES HERE!!」で死ぬ。2 番目のファイルの 3,413 文字を読み取った後、死亡します。

行の半分しか $_ にないため、正規表現が機能しないために発生します。

4

1 に答える 1

2

データが読み取られるファイルにないため、問題はほぼ確実です。

ファイルはコードの以前の部分から生成されたと言います。代わりに、バッファリングの問題があると思われます。コードがファイルへの書き込みを終了したら、 を使用closeして残りのデータをファイルにフラッシュします。すべてがうまくいくと思います。

closeこのように、通話の成功ステータスを確認する必要があります

close FILEHANDLE or die "Unable to close temporary file: $!";

これとは別に、単純にすべてのデータをメモリに保持するのではなく、このような少量のデータに一時ファイルを使用するという賢明さには疑問があります。加えて:

  • すべての変数は、最初の使用ポイントにできるだけ近い場所で常に 宣言する必要がuse strictあります。プログラムの先頭ですべてを宣言することを選択していない限り (非常に悪い考えです)、これを行っていません。use warningsmy

  • 変数名の選択が不安定です。$iファイル名に? そして$o- ええと - 何か?バッファ istelf ではなく、概念的なバッファのサイズ$buffであることを除けば問題ありません。

  • 次の 3 つのパラメーター形式のレキシカル ファイルハンドルを使用する必要がありますopenopen my $fil, '<', $i or die "$!: $i";

  • 正しく使用していた場合は、選択したファイルハンドルと設定を交換するというトリックの代わりに、$|よりすっきりと読みやすく使用できます。これを行うには、オンデマンドでロードする(したがって) Perl 5 バージョン 14 以降を実行していない限り、コードの開始時に必要です。FILE->autoflush$|use IO::HandleIO::FileIO::Handle

  • split /\t/使用している正規表現よりも単純な方が良いと思います。%site_nuまた、このような配列のハッシュを使用したほうがよいようです$site_nu{$j} = [$mirna, $target, $start, $end, $site, $comp_p]

  • 文字列の最後に改行dieを入れると、perl がソース ファイル、データ ファイル、および行番号に関する情報を表示するのを停止します。これは、デバッグ中におそらく役立つでしょう。

  • ソース コードを適切にフォーマットすることで、自分自身や助けを求める人々に恩恵を与えることができます。適切なインデントがないと、コード ブロックの開始位置と終了位置を判別するのが非常に困難になります。

于 2013-03-31T14:04:49.083 に答える