1

作業しているファイルについて説明することから始めます。

./groupA
    ./groupA/fileA.txt
    ./groupA/fileB.txt
    ./groupA/fileC.txt
    ./groupA/fileD.txt

./groupB
    ./groupB/fileA.txt
    ./groupB/fileB.txt
    ./groupB/fileC.txt

etc.

これが私がやりたいことです:

  1. それぞれ数百 MB のサイズのgroupI非常に大きなタブ区切りのテキスト ファイルを指すファイル ハンドルのハッシュまたは配列があります。fileJ

  2. 一度に 1 つのタブ区切り行を読み込んで、ファイル ハンドルをループしたいと思います。すべてのファイルの行をメモリに読み込むことができません。

  3. ファイル ハンドルのループが終了したら、split各行で、各分割配列 (たとえば、5 番目のフィールド) から特定の列のデータを取得し、そのデータを 1 行の出力にマージします。

  4. 手順 2 (各ファイル ハンドルから 1 行を取得) を EOF まで繰り返します。

その後、、、などになりgroupA/mergedOutput.mtxますgroupB/mergedOutput.mtx

問題は、手順 2 と 3 を正しく行う方法がわからないことです。

これが私がこれまでに持っているコードです:

#!/usr/bin/perl

use strict;
use warnings;
use File::Glob qw(glob);

my @groups = qw(groupA groupB groupC);
my ($mergedOutputFn, %fileHandles);

foreach my $group (@groups) {
    $mergedOutputFn = "$group/mergedOutput.mtx";

    # Step 1:
    # Make hash table of file handles

    foreach my $inputFn (<"$group/*.txt">) {
        open my $handle, '< $inputFn' or die "could not open $inputFn\n";
        $fileHandles{$inputFn} = $handle;
    }

    # Steps 2 and 3:
    # Grab a line from each file handle
    # Repeat until EOF

    while(1) {
        my @mergedOutputLineElements = ();
        foreach (sort keys %handles) {
            my $handle = $handles{$_};
            my $line = <$handle>;
            chomp($line);
            my @lineElements = split("\t", $line);
            push (@mergedOutputLineElements, $lineElements[4]);
            last if (! defined $line); # jump out of while loop
        }
        print Dumper join("\t", @mergedOutputLineElements);
    }

    # Step 4:
    # Close handles

    foreach (sort keys %handles) {
        close $handles{$_};
    } 
}

1 つの問題は、次のコードが機能しないことです。

foreach (sort keys %handles) {
    my $handle = $handles{$_};
    my $line = <$handle>;
    ...
}

の値を出力しようとすると$line、次の値が得られGLOBます。

print Dumper $line;
...
GLOB(0x1d769f80)

をどのように誤っ$lineて処理していますか、または Perl 内でこれを行う簡単な方法はありますか?

アドバイスありがとうございます。

編集

固定コードは次のとおりです。

#!/usr/bin/perl

use strict;
use warnings;
use File::Glob qw(glob);

my @groups = qw(groupA groupB groupC);
my ($mergedOutputFn, %fileHandles);

foreach my $group (@groups) {
    $mergedOutputFn = "$group/mergedOutput.mtx";
    open MERGE, "> $mergedOutputFn" or die "could not open handle to $mergedOutputFn\n";

    # Step 1:
    # Make hash table of file handles

    foreach my $inputFn (<"$group/*.txt">) {
        open my $handle, '< $inputFn' or die "could not open $inputFn\n";
        $fileHandles{$inputFn} = $handle;
    }

    # Steps 2 and 3:
    # Grab a line from each file handle
    # Repeat until EOF

    LINE: while(1) {
        my @mergedOutputLineElements = ();
        foreach (sort keys %handles) {
            my $handle = $handles{$_};
            my $line = readline $handle;
            last LINE if (! defined $line); # jump out of while loop
            chomp($line);
            my @lineElements = split("\t", $line);
            push (@mergedOutputLineElements, $lineElements[4]);
        }
        print MERGE join("\t", @mergedOutputLineElements);
    }

    # Step 4:
    # Close handles

    foreach (sort keys %handles) {
        close $handles{$_};
    } 

    close MERGE;
}

ヒントをありがとう!

4

1 に答える 1

2

次のようにファイルハンドルから読み取ることができます。

foreach (sort keys %handles) {
    my $line = readline $handles{$_};
    ...
}
于 2011-03-10T11:22:58.257 に答える