我正在为Netscreen防火墙配置文件编写一个解析器,以创建一些与我使用PIX :: Walker的脚本相同的脚本。我遇到了一个问题,我在parseconfig子中创建的引用在转储1中看起来很好,但在转储2中是空的。我现在正在研究一种更清洁的方法,但我想知道是否有人能告诉我为什么转储2显示引用为空。
#!/usr/bin/perl
use strict;
use Getopt::Std;
use Data::Dumper;
my $usage = "Usage: isg-ppsrpt.pl -d config directory
-d is required
use portproto-rpt.pl -h to get this help\n\n";
my @firewalls = ("foo","bar","baz");
my %opts;
my %configs;
getopts('hd:', \%opts);
if ($opts{h}) { die $usage };
# Parser definition
my %parse;
$parse{service} = sub {
my $ref = shift;
my @elements = split(/\s+/, shift);
@elements[2] =~ /\"(\S+)\"/;
my $name = $1;
my $out;
if ($elements[4] =~ /tcp|udp/) {
$out->{proto} = $elements[4];
$out->{port} = $elements[-1];
}
if ($out) {push @{$ref->{service}{$name}}, $out};
};
foreach (@firewalls) {
my $fw = sprintf "%s\\%s.config",$opts{d},$_;
if (-e $fw) {
$configs{$_} = parseconfig($fw);
} else {
die "Cannot find config file for $_ in \n";
}
}
sub parseconfig {
my $configref;
my $configfile = shift;
open (CONFIG,"$configfile");
foreach my $line (<CONFIG>) {
chomp $line;
my $type = (split(/\s+/,$line))[1];
if ($parse{$type}) {
$parse{$type}($configref,$line);
}
print Dumper(%$configref); # Dump 1
}
close(CONFIG);
print Dumper(%$configref); # Dump 2
return($configref);
}
答案 0 :(得分:2)
sub parseconfig {
my $configref;
....
if ($parse{$type}) {
$parse{$type}($configref,$line);
我不知道这解释了你的问题,但看起来你依靠被调用的函数来填充$ configref。这仅在直接使用$_[0]
(传递的参数$configref
的别名)时才有效;如果它将它分配给词汇并使用它,$configref
本身将保持未定义。在parseconfig中将$configref
初始化为{}
会修复此问题。
答案 1 :(得分:1)
通过自动更新,您可以为$ref
分配哈希引用。但是,该参考永远不会在调用者中分配给$configref
。
更改$ref
不会更改$configref
,因此$configref
仍未定义。由于$_[0]
别名为$configref
,因此更改$_[0]
会更改$configref
。
您必须找到在$ref
和$configref
中放置相同引用的方法。
解决方案1:
$parse{service} = sub {
my $ref = $_[0] ||= {};
...
};
my $configref;
...
$parse{$type}($configref, $line);
解决方案2:
$parse{service} = sub {
my $ref = $_[0];
...
};
my %config;
...
$parse{$type}(\%config, $line);
解决方案3:
$parse{service} = sub {
my %config;
...
return %config;
};
my %config;
...
%config = ( %config, $parse{$type}($line) );