这个对我毫无意义。我有这两个子程序。
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 :(得分:10)
这总是错误的:
if (@_ eq '') {
当为空时,数组在标量上下文中给出0,而不是''。 只是:
if ( ! @_ ) {
足以测试是否没有传递。
但我认为你的意思是确保通过了一个定义的值:
if ( ! defined $_[0] ) {
要知道为什么$_[0]
未定义,我们必须看到声明中的代码,以及它传递给子的位置。
答案 1 :(得分:3)
您的代码的一些基本指示:
elsif
而不是嵌套其他块。-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
顺便说一下,我不知道你在死亡消息中对RED
和RESET
进行了什么,但我觉得用异常处理程序可以更好地实现它。
答案 2 :(得分:2)
如果您只使用一个值的sub,那么您也可以将其复制到变量,而不是使用@_
,如下所示:
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
也会失败。但是,它会给出更好的错误。
此外,如果您正在使用函数的参数,则不使用sub操纵全局变量可能更加一致,而是提供返回值,例如:
...
return %$config_xml;
}
%config_file = load_config_file($config_file_path);
答案 3 :(得分:0)
为了获得上述警告,子例程load_guest_os_file
的第一个参数必须是未定义的(这是声明后的默认值)。
从您显示的源代码中,我可以看到此方案发生的唯一可能性是没有给出有效的选项-g<path>
,因此永远不会为变量$guest_os_file_path
分配值。然后使用未定义的值作为参数调用子例程load_guest_os_file
,如此
load_guest_os_file(undef)
和Perl会发出这些警告。