通过在值 => 中分配数组,在哈希中添加键值对 不能将未定义的值用作 ARRAY 引用



我正在尝试将哈希键值对中的数组分配为键的值。分配后,我试图将其解释并从输出文件中的特定键打印数组值,如您从下面的代码中看到的。

代码在阵列操作部分上不正常。有人可以告诉我我做错了什么吗?

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";

最新更新