我将首先描述我正在使用的文件:
./groupA
./groupA/fileA.txt
./groupA/fileB.txt
./groupA/fileC.txt
./groupA/fileD.txt
./groupB
./groupB/fileA.txt
./groupB/fileB.txt
./groupB/fileC.txt
etc.
以下是我想做的事情:
我为每个groupI
提供了一个散列或文件句柄数组,指向非常大的制表符分隔文本文件fileJ
,每个文件大小几百MB。
我想循环遍历文件句柄,一次读取一个制表符分隔的行。 我无法将所有文件的行读入内存。
一旦我完成了文件句柄的循环,我就想split
每行,从每个分割数组(例如第五个字段)中获取特定的数据列,然后合并数据到输出线。
重复步骤2 - 从每个文件句柄中抓取一行 - 直到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{$_};
}
}
一个问题似乎是以下代码不起作用:
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;
}
感谢您的提示!
答案 0 :(得分:2)
你可以从这样的文件句柄中读取:
foreach (sort keys %handles) {
my $line = readline $handles{$_};
...
}