我想将以下几行数据转换为带有perl的结构化表:
3=884|4=884|5=MBREFUSDCMR|25=113500|824=20120229|387=4.15|248=TLD|280=5
3=884|4=884|5=MBREFUSDCMR|24=1|12=0|10=0|25=113500|824=20120229|280=5
3=884|4=884|5=MBREFUSDCMR|24=1|270=252304|280=5
等号前面的每个值代表的标识符 相应的价值。现在我想制作一张桌子 分析。第一行应包含标识符,并低于其值。标识符中的标识符数量不等 三行必须牢记。缺少值应该是 填充字符串“NA”。所以看起来应该是这样的
3|4|5|24|12|10|25|824|387|248|270|280
884|884|MBREFUSDCMR|NA|NA|NA|113500|20120229|4.15|TLD|NA|5
884|884|MBREFUSDCMR|1|0|0|113500|20120229|NA|NA|NA|5
884|884|MBREFUSDCMR|1|NA|NA|NA|NA|NA|NA|252304|5
@DVK
我的方法是先获取所有变量。那将是表格的标题/第一行。 E.g。
my @data_dirty = <STDIN>;
chomp(@data_dirty);
## get the columns names
my ( @tmp, @var );
foreach my $j (@data_dirty) {
foreach my $i (split /\|/, $j) {
$i =~ s/\[.*\]//g;
$i =~ s/\s+//g;
$i =~ s/(.*)=.*/$1/g;
push(@tmp, $i);
}
}
@var = uniq @tmp;
之后我可能检查每一行是否存在@var
中的变量,如果是,则写入相应的值,否则写入“NA”。但是,我在检查和正确存储数据方面遇到了一些麻烦,以便之后输出看起来符合要求。
答案 0 :(得分:2)
解决这些需求的关键是分而治之。您需要仔细选择子程序。
此处需要加载数据,并且在打印任何表格之前需要先验知所有标识符。
以下示例不按列出的顺序对列进行排序(左侧作为读者的练习):
use strict;
use warnings;
my ( $data, $headers ) = load_data( 'tabular_data.txt' );
print_tabular( $data, $headers );
sub load_data {
my ( $file ) = @_;
open my $fh, '<', $file or die $!;
my ( @records, %fields );
while ( my $line = <$fh> ) {
chomp $line;
my @columns = split /\|/, $line; # Get columns
my %entries = map { split /=/, $_ } @columns; # Populate record,
# keys = fields
push @records, \%entries; # Add to data collection
$fields{$_}++ for keys %entries; # Detect new headers
}
close $fh;
return ( \@records, [ keys %fields ] );
}
sub print_tabular {
my ( $data, $headers ) = @_;
pretty_print( @$headers );
for my $record ( @$data ) {
my @values = map { exists $record->{$_} # exists check needed...
? $record->{$_} # ... otherwise header '0'
: 'NA' # ... would always print 'NA'
} @$headers;
pretty_print( @values );
}
}
sub pretty_print { print join( '|', @_ ), "\n" }