2011-05-23 46 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被稱爲會給這些警告。

相關問題