在 perl 中,这个工作的工具是一个散列片。
您可以使用@hash{@keys} 访问哈希值。
所以是这样的:
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;
my @headers;
my $type;
my @rows;
#iterate data - would do this with a normal 'open'
while ( <DATA> ) {
#set headers if the leading word is all upper case
if ( m/^[A-Z]+\s/ ) {
#seperate out type (VEG/FRUIT) from the other headings.
chomp ( ( $type, @headers ) = split );
#print for debugging
print Dumper \@headers;
}
else {
#create a hash to store this row.
my %this_row;
#split the row on whitespace, capturing name and ordered fields by header row.
( my $name, @this_row{@headers} ) = split;
#insert name and type into the hash
$this_row{name} = $name;
$this_row{type} = $type;
#print for debugging
print Dumper \%this_row;
#store it in @rows
push ( @rows, \%this_row );
}
}
#print output:
#header line
print join ("\t", "name", "type", @headers ),"\n";
#iterate rows, extract ordered by _last_ set of headers.
foreach my $row ( @rows ) {
print join ( "\t", $row->{name}, $row->{type}, @{$row}{@headers} ),"\n";
}
__DATA__
FRUIT MSMC1 MSMC24 MSMC2 MSMC10
Apple 1 2 3 2
Pear 2 1 4 5
VEG MSMC24 MSMC1 MSMC2 MSMC10
Onion 2 1 3 2
Radish 0 3 9 3
注意 - 我已使用 Data::Dumper 进行诊断 - 这些行可以删除,但我留下它们是因为说明发生了什么。
同样从<DATA> 读取——通常你会打开一个文件句柄,或者只是使用while ( <> ) { 来读取STDIN 或命令行上指定的文件。
输出的顺序是基于最后一个标题行'seen' - 您当然可以对其进行排序或重新排序。
如果您需要处理不匹配的列,这将在缺少的列上出错。在这种情况下,我们可以拆分map 以填充任何空白,并为headers 使用散列以确保我们捕获所有空白。
例如;
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;
my @headers;
my %headers_combined;
my $type;
my @rows;
#iterate data - would do this with a normal 'open'
while ( <DATA> ) {
#set headers if the leading word is all upper case
if ( m/^[A-Z]+\s/ ) {
#seperate out type (VEG/FRUIT) from the other headings.
chomp ( ( $type, @headers ) = split );
#add to hash of headers, to preserve uniques
$headers_combined{$_}++ for @headers;
#print for debugging
print Dumper \@headers;
}
else {
#create a hash to store this row.
my %this_row;
#split the row on whitespace, capturing name and ordered fields by header row.
( my $name, @this_row{@headers} ) = split;
#insert name and type into the hash
$this_row{name} = $name;
$this_row{type} = $type;
#print for debugging
print Dumper \%this_row;
#store it in @rows
push ( @rows, \%this_row );
}
}
#print output:
#header line
#note - extract keys from hash, not the @headers array.
#sort is needed to order them, because default is unordered.
print join ("\t", "name", "type", sort keys %headers_combined ),"\n";
#iterate rows, extract ordered by _last_ set of headers.
foreach my $row ( @rows ) {
print join ( "\t", $row->{name}, $row->{type}, map { $row->{$_} // '' } sort keys %headers_combined ),"\n";
}
__DATA__
FRUIT MSMC1 MSMC24 MSMC2 MSMC10 OTHER
Apple 1 2 3 2 x
Pear 2 1 4 5 y
VEG MSMC24 MSMC1 MSMC2 MSMC10 NOTHING
Onion 2 1 3 2 p
Radish 0 3 9 3 z
在这里,map { $row->{$_} // '' } sort keys %headers_combined 获取散列的所有键,按顺序返回它们,然后从行中提取该键 - 如果未定义,则给出一个空格。 (这就是// 所做的)