我正在尝试将散列键值对中的数组指定为键的值。在分配之后,我正在尝试取消引用它并从输出文件中的特定键打印数组值,如下面的代码所示。
代码在数组操作部分上运行不正常。有人能告诉我我做错了什么吗?
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\,Col5\n";
# 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 ($_ =~ /^Total\s+records\s+in\s+TAR\s+\(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行使用未定义的值作为ARRAY引用。”
问题是你在错误的地方打电话给print_file
。
想象一下,您一次解析一行文件。您的代码解析第一行并填充$ref->{code}
。但是你在一个部分填充的print_file
上调用$ref
所以它不起作用。
您的代码也没有重置任何使用的变量,因此当它在文件中前进时,$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 ($_ =~ /^Total\s+records\s+in\s+TAR\s+\(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";
在forloop块中的第二个正则表达式匹配之前,$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}
键指定匿名数组引用(因为$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 => [],
}
附:另请注意,我在join()
函数中使用了圆括号而不是方括号(尽管您实际上并不需要)。