Может кто-нибудь сказать мне, почему моя ссылка не возвращается? - PullRequest
1 голос
/ 07 апреля 2011

Я пишу парсер для файлов конфигурации брандмауэра Netscreen для создания некоторых сценариев, которые выполняют те же действия, что и сценарии, которые я использую с помощью PIX :: Walker.Я столкнулся с проблемой, когда ссылка, которую я создаю в sub parconconfig, выглядит хорошо в Dump 1, но пуста в Dump 2. Я сейчас работаю над более чистым подходом, но мне было интересно, если кто-нибудь может сказать мне, почему Dump 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);
}

Ответы [ 2 ]

2 голосов
/ 07 апреля 2011
sub parseconfig {
    my $configref;
    ....
    if ($parse{$type}) {
        $parse{$type}($configref,$line);

Я не знаю, что это объясняет вашу проблему, но похоже, что вы используете вызываемую функцию для заполнения $ configref.Это будет работать, только если оно напрямую использует $_[0] (псевдоним переданного параметра $configref);если он присваивает его лексическому и использует его, сам $configref останется неопределенным.Инициализация $configref до {} в parseconfig исправляет это.

1 голос
/ 07 апреля 2011

Посредством автовивификации вы присваиваете ссылку на хэш $ref. Тем не менее, эта ссылка никогда не назначается fo $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) );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...