我有这种形式的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
将是一个更好的解决方案。它如何减少使用嵌套数据结构的需要?
答案 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;
处理,并且正确地对您的哈希进行词汇定义。