我正在尝试将哈希键值对中的数组分配为键的值。分配后,我试图将其解释并从输出文件中的特定键打印数组值,如您从下面的代码中看到的。
代码在阵列操作部分上不正常。有人可以告诉我我做错了什么吗?
use strict;
use warnings;
use Data::Dumper;
# File input
my $in_file = 'log.txt';
# Output file
my $out_file_name = 'output.csv';
open(my $fout, '>', $out_file_name);
# print header csv
print $fout "Col1,Col2,Col3,Col4,Col5n";
# Read the input file
open(FH, '<', $in_file) or die "Could not open file '$in_file' $!";
my @log_file = <FH>;
# print Dumper(@log_file),"n";
close (FH);
# my @test_val;
my ($read, $ref, $val_county, $val_rec, $val_tar, $val_print, @test_values, $status);
foreach(@log_file) {
# print $_;
if ($_ =~ /t+(?<county_name>(?!Total).+)s+/i) {
$ref->{code} = $+{county_name};
$val_county = $ref->{code};
} elsif ($_ =~ /^Totals+recordss+ins+TARs+(pr.+):s+(?<tar_records>.+)$/i) {
$ref->{code} = $val_county;
push(@test_values, $+{tar_records});
$ref->{tar_rec} = @test_values;
# $val_rec = $ref->{tar_rec};
# $val_rec =~ s/.//g;
}
&print_file($ref);
}
sub print_file {
my $ref = shift;
my $status = shift;
print $fout join(",", $ref->{code}, [@{$ref->{tar_rec}}]), "n"; # Line 68
print Dumper($ref);
}
close $fout;
print "Done!","n";
代码是提供错误的错误:"不能在test_array_val_hash.pl行68上使用未定义值作为数组参考。"
直到轨道块中的第二个正则键为止,$ref->{tar_rec}
键将不会分配一个值 - 并且将不确定。以下片段 - 基于您自己的代码 - 突出显示问题。
#!/usr/bin/perl -w
my @tar_records = (15,35,20);
my $ref = {
code => 'Cork',
tar_rec => @tar_records,
};
sub print_info {
my $ref = shift;
print join(", ", $ref->{code}, (@{$ref->{tar_rec}})), $/;
}
print_info($ref);
# Once we 'undefine' the relevant key, we witness the afore-
# mentioned error.
undef $ref->{tar_rec};
print_info($ref);
要避免此错误,您可以在for循环之前分配一个匿名数组引用到 $ref->{tar_rec}
key (因为 $ref->{tar_rec}
是累积值)。
# Be sure not to declare $ref twice!
my ($read, $val_county, $val_rec, $val_tar, $val_print, @test_values, $status);
my $ref = {
code => '',
tar_rec => [],
}
P.S。还请注意,我在join()
函数中使用了圆括号,而不是方括号(尽管您实际上也不需要)。
问题是您在错误的位置调用print_file
。
想象一下,您一次将文件分解为一行。您的代码解析了第一行,并填充$ref->{code}
。但是然后您在部分填充的$ref
上调用print_file
,以使其不起作用。
您的代码也没有重置任何使用的变量,因此随着文件的进行,$ref
的内容将会增长。
下面的代码通过隐式设置$ref->{tar_rec}
中的空数组来解决第一个问题,并且仅在记录启动新的数组或在文件中完成读取时才打印出记录。由于$ref->{tar_rec}
是一个数组,因此可以通过直接推入它而不是依靠@test_values
来解决另一个问题。只是为了增加安全性,它为$ref
分配了一个空的哈希。
if(open(my $fh, '<', $in_file)) {
my $ref;
my $val_county;
foreach(<$fh>) {
# print $_;
if ($_ =~ /t+(?<county_name>(?!Total).+)s+/i) {
if(defined($val_county)) {
print_file($ref);
}
$ref={};
$val_county = $+{county_name};
$ref->{code} = $val_county;
$ref->{tar_rec} = [];
} elsif ($_ =~ /^Totals+recordss+ins+TARs+(pr.+):s+(?<tar_records>.+)$
push @{$ref->{tar_rec}}, $+{tar_records};
}
}
if(defined($ref)) {
print_file($ref);
}
close($fh);
} else {
die "Could not open file '$in_file' $!";
}
您还打印出数组错误
print $fout join(",", $ref->{code}, [@{$ref->{tar_rec}}]), "n";
您不需要@{$ref->{tar_rec}}
周围的任何括号 - 它将被视为要传递给join
的值列表。
print $fout join(",", $ref->{code}, @{$ref->{tar_rec}}), "n";