2011-05-23 42 views
1

这对我来说毫无意义。我有这两个子程序。在我的程序中导致警告“使用未初始化的值”的原因是什么?

sub load_config_file { 
    if (@_ eq '') { 
     die RED . "No configuration file defined" . RESET . "\n"; 
    } else { 
     if (! -e "@_") { 
      die RED . "@_ not found!" . RESET . "\n"; 
     } else { 
      if (`cat @_` eq '') { 
       die RED . "$config_file_path is an empty file!" . RESET . "\n\n"; 
      } else { 
       print "Configuration file:" . GREEN . "@_" . RESET . "\n"; 
       my $xml_obj = XML::Simple->new(); 
       my $config_xml = $xml_obj->XMLin("@_", SuppressEmpty => 1); 
       %config_file = %$config_xml; 
      } 
     } 
    } 
} # End load_config_file 

sub load_guest_os_file { 
    if (@_ eq '') { 
     die RED . "No guest operating system file defined" . RESET . "\n"; 
    } else { 
     if (! -e "@_") { 
      die RED . "@_ not found!" . RESET . "\n"; 
     } else { 
      if (`cat @_` eq '') { 
       die RED . "@_ is an empty file!" . RESET . "\n\n"; 
      } else { 
       print "Guest OS file:" . GREEN . "@_" . RESET . "\n"; 
       my $xml_obj = XML::Simple->new(); 
       my $guest_os_xml = $xml_obj->XMLin("@_", SuppressEmpty => 1); 
       %guest_os_file = %$guest_os_xml; 
      } 
     } 
    } 
} # End load_guest_os_file 

他们的目的是加载我的脚本所需的特定配置文件。第一个,load_config_file,作品完美。但是,当我移动到第二个,load_guest_os_file,我从Perl中得到这些错误:

Use of uninitialized value $_[0] in join or string at analyze.pl line 146. 
Use of uninitialized value $_[0] in join or string at analyze.pl line 148. 

在我的脚本146线是

if (! -e "@_") { 

和线路148

die RED . "@_ not found!" . RESET . "\n"; 

什么我错过了吗?当我调用子程序这样的:

load_config_file($config_file_path) 
load_guest_os_file($guest_os_file_path) 

...分配给这两个变量的值

my $config_file_path = './config.xml' 

my $guest_os_file_path = './guest_os.xml' 

编辑:我也要添加来自处理的命令行参数的两个变量的值Getopt::Long。如果没有赋值,变量只是“声明”,我认为这是一个术语。我没有给它赋值,它只是my $config_file_path;my $guest_os_file_path;

更新

这是从剧本开始的代码。

#!/usr/bin/perl 
use strict; 
use warnings; 

# Modules to load 
use Getopt::Long; 
use Term::ANSIColor qw(:constants); 
use XML::Simple; 
use Net::Ping; 
use Net::OpenSSH; 
use Data::Dumper; 

# Script version 
my $version = 'v0.6'; 

my (%config_file, %guest_os_file, %machines_xml, $ssh_obj); 

my @selected_mode; 

# Configuration file 
my $config_file_path; 

# Guest OS file 
my $guest_os_file_path; 

# Exclusion file 
my $exclude_file_path; 

# Disables snapshot capture 
my $no_snapshots = 0; 

my $logfile_path; 

my $verbose = 0; 

# Program modes 
my %program_modes = (
    analyze => \&analyze, 
    backup => \&backup, 
    restore => \&restore, 
    help => \&help, 
); 

GetOptions(
    'c=s' => \$config_file_path, 
    'e=s' => \$exclude_file_path, 
    'g=s' => \$guest_os_file_path, 
    'l=s' => \$logfile_path, 
    'v' => \$verbose, 
    'x' => \$no_snapshots, 
    'a' => sub { push @selected_mode, "analyze" }, 
    'b' => sub { push @selected_mode, "backup" }, 
    'h' => sub { push @selected_mode, "help" }, 
    'r' => sub { push @selected_mode, "restore" }, 
    's' => sub { push @selected_mode, "setup" }, 
); 

# Show the help menu if no program mode has been selected 
if (@selected_mode == 0) { 

    help(); 

# Throw an error and show the help menu if too many modes are selected 
} elsif (@selected_mode > 1) { 

    print RED . "Too many program modes specified" . RESET . "\n"; 

    print "See help menu [-h] for further information\n"; 

# Run the selected program mode 
} elsif (@selected_mode == 1) { 

    if ($selected_mode[0] eq 'help') { 

     help(); 

    } else { 

     # Die unless user is root 
     die RED . "You must be have superuser permissions to run this script" . RESET . "\n" unless ($> == 0); 

     system "clear"; 

     print "Solignis's VMware $selected_mode[0] script $version for ESX\\ESX(i) 4.0+\n"; 

     load_config_file($config_file_path); 

     if ($selected_mode[0] eq 'analyze') { 

      load_guest_os_file($guest_os_file_path); 

     } else { 

      ###### 

     } 

    } 

} 
+0

那么是什么导致了警告?这是我猜测下面? – hexcoder 2011-05-24 15:23:29

回答

3

在你的代码中genereal指针:

  • 考虑使用elsif代替以往嵌套else块。
  • 如果你有一堆错误条件被过滤出来,请考虑使用语句修饰符if /除非逻辑。
  • 考虑使用-z-s来获取文件大小(请参阅http://perldoc.perl.org/functions/-X.html)。
  • 解压缩@_位于子程序的顶部。
  • 尽量减少全局变量的使用。显式传递所有数据进出你的潜艇。

这是你的第一子的清理版本:

sub load_config_file { 
    my $config_file = shift; 

    die RED . "No configuration file defined" . RESET . "\n" 
     unless defined $config_file; 

    die RED . "$config_file not found!" . RESET . "\n" 
     unless -e $config_file; 

    die RED . "$config_file_path is an empty file!" . RESET . "\n\n" 
     if -z $config_file; 


    print "Configuration file:" . GREEN . "@_" . RESET . "\n"; 

    my $xml_obj = XML::Simple->new(); 
    my $config_xml = $xml_obj->XMLin("@_", SuppressEmpty => 1); 

    return $config_xml; 

} # End load_config_file 

BTW,我不知道你要什么就用RED S和RESET在你的模具的消息,但我有一个觉得用异常处理程序可以更好地实现它。

+0

的开头发布声明非常好,使用'-z'是我一直在寻找的东西。 – ianc1215 2011-05-23 18:44:36

10

这将始终是假:

if (@_ eq '') { 

空白时,该阵列中的标量上下文给出0,而不是 ''。 刚:

if (! @_) { 

是足以测试,如果没有来过了。

但我认为你实际上意味着,以确保一个定义的值传递:

if (! defined $_[0]) { 

知道为什么$_[0]是不确定的,我们不得不看到从申报到它传递到代码分。

+0

我将从脚本 – ianc1215 2011-05-23 18:56:42

2

如果使用潜艇只有一个值,你不妨复制的,超过一个变量,而不是使用@_,就像这样:

sub load_guest_os_file { 
    my $path = shift; 

要执行可以做到更好的测试,他们不需要被对方内线,因为唯一的结果就是die

$path || die RED . "No guest operating system file defined" . RESET . "\n"; 
-e $path || die RED . "$path not found!" . RESET . "\n"; 
-s $path || die RED . "$path is an empty file!" . RESET . "\n\n"; 

-e检查并不功能必需的,因为-s也将失败,如果文件丢失。不过,它会带来更好的错误。

... 
    return %$config_xml; 
} 

%config_file = load_config_file($config_file_path); 
+0

是的,我做了你的建议,我喜欢它。 – ianc1215 2011-05-24 00:22:20

0

为了得到:

此外,如果你正在使用参数的函数,它可能不操纵全局变量与子,而是给出一个返回值,如更加一致上面提到的警告,子程序load_guest_os_file的第一个参数必须是未定义的(这是声明后的默认值)。

从您显示的源代码中,我可以看到这种情况发生的唯一可能性是没有给出有效的选项-g<path>,因此变量$guest_os_file_path从来没有被赋值。然后子程序load_guest_os_file将有一个未定义的值作为参数,这样

load_guest_os_file(undef) 

和Perl被称为会给这些警告。

相关问题