使用Perl将不规则数据转换为结构化表

时间:2012-03-02 22:00:20

标签: perl transform

我想将以下几行数据转换为带有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”。但是,我在检查和正确存储数据方面遇到了一些麻烦,以便之后输出看起来符合要求。

1 个答案:

答案 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" }