Transposing CSV data in Perl

后端 未结 2 674
臣服心动
臣服心动 2020-12-21 06:42

I am a Perl beginner and currently working on a Perl script to automate some of our tasks. One script that I\'m working on involves extracting performance data from our syst

相关标签:
2条回答
  • 2020-12-21 07:16

    You made one simple, but critical mistake.

    split [ /,/ ] 
    

    should be

    [ split /,/ ]
    

    The syntax for split is

    split /PATTERN/, EXPR, LIMIT
    

    Where the latter two are optional. What you are doing is passing an anonymous array ref as PATTERN, which most likely gets stringified into something like ARRAY(0x54d658). The result is that the line is not split, and the whole line is pushed onto the array. Later on, that will cause the dereference of $row to fail with the error

    Can't use string ("29-Aug-2013,3.68,3.63,3.75,3.65,"...) as an ARRAY ref while "
    strict refs" in use at foo.pl line 18, <F1> line 7.
    
    0 讨论(0)
  • 2020-12-21 07:18

    Here is my Perl program to transpose row data into columns. A row starts with the headline name followed by one or more values. In my case I needed to remove the date (mm/dd/yyyy) from the headlines so the remainder of the headline field would be unique across multiple rows.

    sub usage { << "EOF";
    
    Convert rows to columns.
    Remove dates from column headings. 
    
    Usage:
        perl $0
    Example:
       $0 data-to-transpose.txt
    
    Source data:
        header1, row1Value1, row2Value2
        header2, row2Value1
        header3 11/31/2011, row3Value1, row3Value2
    Output:
        header1, header2, header3
        row1Value1, row2Value1, row3Value1
        row1Value2, , row3Value2
    
    EOF
    }
    #
    #-------------------------------------------------------------------------------
    
    use 5.010;
    use strict;
    use warnings;
    
    # use Data::Dumper;
    sub printColumns;
    
    my $inFile = shift or die usage();
    # @ARGV = ('.') unless @ARGV;
    
    my @headers;        # Order list of column headers
    my %data;           # map{colHeader, arrayColSourceData }
    my $colCnt = 0;     # maximum number of columns in source data, header, value1, value2, ....
    my $printColHeaders = 1;
    
    my %hasharray; open (my $fh, "<", $inFile) or die "can't open the $inFile";
    while (<$fh>) {
        chomp;
        my @parts = split /,/; 
    
        if (@parts > 1) {
            # Remove date from heading field
            (my $header = $parts[0]) =~ s/[0-9]+\/[0-9]+\/[0-9]+//;
    
            if (!exists $data{$header}) {
               push @headers, $header;
            }
    
            my $have = $data{$header};
            if (defined $data{$header}) {
                if ($printColHeaders == 1) {
                    $printColHeaders = 0;
                    foreach my $col (@headers) {
                        print "$col,";
                    }
                    print "\n";
                }
    
                printColumns();
    
                foreach my $col (@headers) {
                     $data{$col} = undef;
                }
            } 
    
            $data{$header} = \@parts;
            $colCnt = (@parts > $colCnt) ? @parts : $colCnt;
        }
    } 
    
    printColumns();
    print "\n";
    
    foreach my $col (@headers) {
        print "$col,";
    }
    print "\n";
    
    #### Subs 
    sub printColumns() {
        for my $row (1 .. $colCnt-1) {
            foreach my $colHeader (@headers) {
                my $colData = $data{$colHeader};
                if (defined $colData) {
                    my $len=@$colData;
                    if (defined $colData && $row < @$colData) {
                        print "$colData->[$row], ";
                    } else {
                        print ", ";
                    }
                } else {
                    print ", ";
                }
            }
            print "\n";
        } 
    }
    
    0 讨论(0)
提交回复
热议问题