使用Perl中哈希散列数组解析CSV文件

时间:2016-01-15 10:36:34

标签: perl csv file-io hash

我有这种形式的CSV数据:

Sl.No, Label, Type1, Type2...
1, "label1", Y, N, N...
2, "label2", N, Y, Y...
...

哪里" Y"和" N"表示是否要将相应的标签打印到文件中。

while ( <$fh> ) {    #Reading the CSV file

    $filter = $_;
    chomp $filter;
    $filter =~ tr/\r//d;

    if ( $. == 1 ) {
        @fieldNames = split ",", $filter;
    }
    else {
        @fields = split ",", $filter;
        $numCustomers = scalar(@fields) - 2;
        push @labels, $fields[2];

        for ( $i = 0; $i < $numCustomers; $i++ ) {

            for ( $j = 0; $j < scalar(@labels); $j++ ) {
                $customer[$i][$j] = $fields[ 2 + $i ];
            }

            $custFile = "customer" . $i . "_external.h";

            open( $fh1, ">", $custFile ) or die "Unable to create external header file for customer $i";
        }
    }
}

for ( $i = 0; $i < scalar(@labels); $i++ ) {

    for ( $j = 0; $j < $numCustomers; $j++ ) {

        $Hash{ $fieldNames[ 2 + $i ] }->{ $labels[$i] } = $customer[$j][$i];
        push @aoh, %Hash;    #Array of hashes
    }
}

my @headerLines = read_file($intFile);  # read the internal file, and copy only
                                        # those lines that are not marked with
                                        # "N" in the CSV file to the external file.

# iterate over elements of each hash and print the labels only if value is 'Y'

foreach my $headerLine (@headerLines) {

    chomp $headerLine;

    for $i ( 0 .. $#aoh ) {

        for my $cust1 ( sort keys %{ $aoh[$i] } ) {    #HERE

            for my $reqLabel1 ( keys %{ $aoh[$i]{$cust1} } ) {

                print "$cust1, $reqLabel1 : $aoh[$i]{$cust1}{$reqLabel1}\n";

                if ( $aoh[$i]{$cust1}{$reqLabel1} eq "Y" ) {

                    for ( $j = 0; $j < $numCustomers; $j++ ) {
                        $req[$j][$i] = $reqLabel1;
                    }
                }
                else {
                    for ( $j = 0; $j < $numCustomers; $j++ ) {
                        $nreq[$j][$i] = $reqLabel1;
                    }
                }
            }

        }

        if ( grep { $headerLine =~ /$_/ } @nreq ) {
            next;    #Don't print this line in the external file
        }
        else {
            print $fh1 $headerLine . "\n";    #print this line in the external file
        }
    }
}

抱怨&#34;不能使用字符串Type1作为哈希REF&#34;,指的是标记为#HERE的行。

我尝试过在任何地方都倾销数据结构,但我不确定这是从哪里出来的。

任何见解都将不胜感激。

我收到的反馈是,使用Text::CSV将是一个更好的解决方案。它如何减少使用嵌套数据结构的需要?

2 个答案:

答案 0 :(得分:3)

我只保留一组打开的文件句柄(如果没有太多类型)并在逐行读取文件时打印它们。

#!/usr/bin/perl
use warnings;
use strict;

chomp( my $header = <> );
my @names = split /, /, $header;

my @handles;
for my $type (@names[ 2 .. $#names ]) {
    open my $fh, '>', $type or die "$type: $!";
    push @handles, $fh;
}

while (<>) {
    chomp;
    my @fields = split /, /;
    for my $index (0 .. $#handles) {
        print { $handles[$index] } $fields[1], "\n" if 'Y' eq $fields[ $index + 2 ];
    }
}

我使用以下输入来测试它:

Sl.No, Label, Type1, Type2, Type3, Type4
1, "label1", Y, N, Y, N
2, "label2", N, Y, Y, N

如果您的输入包含\r行结尾,请将binmode设置为:crlf

答案 1 :(得分:3)

好的,使用Text::CSV可以轻松解决问题。我建议看一下重写,或者重新解决你的问题。

但问题实际上是这样的:

push @aoh, %Hash;                #Array of hashes

根本不会创建一个哈希数组。这会从%Hash中提取所有元素(除了要配对的键和值之外,没有特定的顺序)并将它们插入@aoh

可能想要:

push @aoh, \%Hash;

或者也许:

push @aoh, { %Hash }; 

我并不完全清楚,因为您正在重复使用%Hash,因此您可能会重复。这最好由use strict; use warnings;处理,并且正确地对您的哈希进行词汇定义。