为什么我在这个Perl程序中收到有关未初始化值的警告?

时间:2014-10-07 13:48:05

标签: perl subroutine

我收到这些错误

  

Use of uninitialized value $vm_name in pattern match (m//) at testscript.pl line 164, <STDIN> line 1.

     

Use of uninitialized value $vm_name in concatenation (.) or string at testscript.pl line 173, <STDIN> line 1.

有人可以帮忙吗?我有一种感觉,它与子程序有关,但无法弄清楚。我是Perl的新手,并且已经花了好几个小时。

# !/usr/bin/perl

use strict;
use warnings;
use feature ":5.10";

###############################################################################
# Static Variables
my $templateID = "XXXXXXXXXX";
my $serviceID  = "XXXXXXXXXXX";
###############################################################################

###############################################################################
# Global Variables
my $zone;
my $input;
my $zone_ID;
my $vm_name;
my $net_default;
my $net_secondary;
my $vm_ID;
my $start;
my $char_count;
my $ipaddr_1;
my $ipaddr_2;
###############################################################################

# ----------------------- BASIC CONFIGURATIONS [ZONES] ------------------------

print " *** ";
print "
ZONES: paris, milan, berlin, geneva, amsterdam, london, slough";
print " which zone would you like to deploy to? \n ";

# Capture input for ZONE
$input = <STDIN>;

# Data formatting
$input =~ s/^\s+|\s+$|^\t//g;
$zone = lc $input;

# Declare ZONE to USER
print "You are deploying to $zone \n";

# Map input to function

# ZONE PARIS
if ($zone eq "paris") {
   print "Deploying to $zone\n";
   # assign zone id
   $zone_ID = "374b937d-2051-4440-b02c-a314dd9cb27e";
}

# ZONE MILAN
elsif ($zone eq "milan") {
   print "Deploying to $zone\n";
   # assign zone id
   $zone_ID = "58848a37-db49-4518-946a-88911db0ee2b";
}

# ZONE BERLIN
elsif ($zone eq "berlin") {
   print "Deploying to $zone\n";
   # assign zone id
   $zone_ID = "fc129b38-d490-4cd9-acf8-838cf7eb168d";
}

# ZONE GENEVE
elsif ($zone eq "geneva") {
   print "Deploying to $zone\n";
   # assign zone id
   $zone_ID = "1ef96ec0-9e51-4502-9a81-045bc37ecc0a";
}

# ZONE AMSTERDAM
elsif ($zone eq "amsterdam") {
   print "Deploying to $zone\n";
   # assign zone id
   $zone_ID = "3c43b32b-fadf-4629-b8e9-61fb7a5b9bb8";
}

# ZONE SLOUGH
elsif ($zone eq "slough") {
   print "Deploying to $zone\n";
   # assign zone id
   $zone_ID = "5343ddc2-919f-4d1b-a8e6-59f91d901f8e";
}

# ZONE LONDON
elsif ($zone eq "london") {
   print "Deploying to $zone\n";
   # assign zone id
   $zone_ID = "f6b0d029-8e53-413b-99f3-e0a2a543ee1d";
}

# ELSE
else {
   print "Please choose a ZONE";
   system('./deploy_vm');
}

# SUBROUTINE: Assigning Virtual Machine name
sub vm_name {

   # Name of Virtual Machine
   print "Enter name of Virtual Machine: \n";
   print "[VDC Bug: Please do not include '_' in the name]\n";
   my $vm_name = <STDIN>;

   # Data formatting
   $vm_name =~ s/^\s+|\s+$//g;
   print("VM Name: $vm_name");

}

# Apply input filters (no underscores, length constraints)
if (my $vm_name =~ /_/) {
   return ('underscore error');
   print "Cannot use underscore in VM name, please try again";
   vm_name();
}

# DisPlay config
print "
$vm_name will be provisioned with:
1GB HDD and compute offering of 2CPUs with 2GB-RAM";

# ----------------------- NETWORK CONFIGURATIONS ------------------------------

# Gather network information
print "available networks in $zone";
system('cloudmonkey list networks zoneid=$zone_id filter=name,id');

# Users to choose Networks through display
print "";

# Default NIC & IP address
print "please enter Network ID for Default NIC:\n";
$net_default = <STDIN>;

# IP Address DEFAULT
print "please enter IP address\n";
$ipaddr_1 = <STDIN>;

# formatting IP address
$ipaddr_1 =~ m/^\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/;

# SECONDARY NIC & IP address
print "please enter Network ID for secondary NIC";
$net_secondary = <STDIN>;

# IP Address SECONDARY
print "please enter IP address\n";
$ipaddr_2 = <STDIN>;

# Formatting IP address
$ipaddr_2 =~ m/^\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/;

print "IP ADDRESS is $ipaddr_2\n";

# Deployment notice
print "... deploying ... \n";

# Provision Machine

# + startvm=false due to provisioning constraints

system('cloudmonkey deploy virtualmachine startvm=false name=$vm_name diplayname=$vm_name zoneid=$zone_id templateid=$templateID serviceofferingid=$serviceID networkids=$net_default ipaddress=$ipaddr_1');

# Add second network to VM
print "Adding second network to VM";
system('cloudmonkey addNicToVirtualMachine networkid=$network_id_second ipaddress=$ip_address_second virtualmachineid=$vm_id');

# Display machine ID
print "$vm_ID";
my $feedback = system('cloudmonkey list networks zoneid=$zone_id filter=name,id');

# ## ## ## ## ## ## ## ## ## ## ## ## ## ## #
# #     Sotiris Comments     # #
# ## ## ## ## ## ## ## ## ## ## ## ## ## ## #
# if (lc($feedback) =~ /error/) {
#    Warn user and fall back to known state. }

# User to copy&paste ID
print "Paste VM ID:\n";
$vm_ID = <STDIN>;

# Data Validation
$vm_ID      =~ s/^\s+|\s+$//g;
$vm_ID      = lc $vm_ID;
$char_count = length($vm_ID);

# IF statement to impliment length validation
if ($char_count != 36) {
   print "your ID is too long/short";
}

# Start Virtual Machine?
print "Start Virtual Machine $vm_name?";
$start = <STDIN>;

if ($start eq "yes") {
   system('');
}
elsif ($start eq "no") {
   system('');
}

# done!

3 个答案:

答案 0 :(得分:4)

你发布了一段可怜的Perl代码,你可能已经把它写在一个块中。编程不是那样的,特别是在类似脚本的语言中,你应该在测试之前一次只编写两到三行,它可以按预期工作。这样,如果你有一个问题,它可能只是几行代码的输入你知道,但你的行为你无法解释。在这种情况下,您的Use of uninitialized value错误是您最不担心的。

  • 声明应尽可能接近其第一个使用点。

  • 评论应保持绝对最小。一个程序包含一个在没有添加注释的情况下难以理解的构造是非常罕见的,并且你的程序通过不必要的评论大约100%膨胀

  • 区域和区域ID之间的映射最好实现为Perl哈希,而不是if / elsif / else

  • 除了测试vm_name之外,永远不会调用if (my $vm_name =~ /_/) { ... }子例程,并且您在此使用my声明了一个新的$vm_name,它将始终undef

  • 您对formatting IP address发表评论的行根本没有格式化。他们测试变量的内容是否与正则表达式匹配,然后忽略并丢弃测试结果

  • system的调用使用单个引号,因此字符串会逐字传递给cloudmonkey程序,而插值完成。例如,变量名$vm_name$zone_id$templateID$serviceID被其值替换

还有几个问题,但我强烈建议,正如我在开始时所说的那样,你应该以非常小的部分逐步编写程序。通过这种方式,您可以愉快地看到您的代码在行动和萎缩,并且确信您在写作时确实拥有坚实的基础。

答案 1 :(得分:1)

if (my $vm_name =~ /_/)

会一直警告Use of uninitialized value $vm_name in pattern match警告,因为你错误地在my条件if内声明了另一个词法。

此外,您应该将用户输入清理为

my $vm_name = <STDIN>;
如果用户按Ctrl-D或管道输入结束,则

返回undefined。

答案 2 :(得分:0)

你已经到了输入的末尾,但是你假装你真的读过了。也许你想要添加

die "Premature EOF\n" if !defined($vm_name);

my $vm_name=<STDIN>;