作業しているファイルについて説明することから始めます。
./groupA
./groupA/fileA.txt
./groupA/fileB.txt
./groupA/fileC.txt
./groupA/fileD.txt
./groupB
./groupB/fileA.txt
./groupB/fileB.txt
./groupB/fileC.txt
etc.
これが私がやりたいことです:
それぞれ数百 MB のサイズの
groupI
非常に大きなタブ区切りのテキスト ファイルを指すファイル ハンドルのハッシュまたは配列があります。fileJ
一度に 1 つのタブ区切り行を読み込んで、ファイル ハンドルをループしたいと思います。すべてのファイルの行をメモリに読み込むことができません。
ファイル ハンドルのループが終了したら、
split
各行で、各分割配列 (たとえば、5 番目のフィールド) から特定の列のデータを取得し、そのデータを 1 行の出力にマージします。手順 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;
}
ヒントをありがとう!