[英]how can I restart a “do-while” loop after breaking out of a foreach loop?
我的配置脚本中有一小段代码,想法是加载配置然后检查每个密钥是否输入了主机名。 但是,如果发现配置包含相同的主机名,则会被拒绝,并显示一条警告消息,指出已存在具有该主机名的配置。
问题是我需要的foreach循环来检查哈希键是否存在等重启do-while循环使其他主机名称可以尝试或者用户可以^C
出来的脚本。
这是片段;
my $host;
do {
print "Enter the hostname or IP of the ESXi server: ";
chomp($host = <STDIN>);
if ($host eq '') {
print "You must enter a hostname or IP address!\n";
} elsif ($host ne '') {
# We need to catch duplicate configurations for we don't do the same work twice
foreach (keys %config) {
if ($config{$_}{host} ne $host) {
last;
} elsif ($config{$_}{host} eq $host) {
warn "Configuration for $host already exists!\n";
}
}
if ($ping_obj->ping($host)) {
$config{$config_tag}{host} = $host;
} elsif (! $ping_obj->ping($host)) {
print RED . "Ping test for \'$host\' failed" . RESET . "\n";
}
$ping_obj->close();
}
} while ($config{$config_tag}{host} eq 'undef');
这就是模板哈希的样子。
my %template = (
host => 'undef',
port => 'undef',
login => {
user => 'undef',
password => 'undef',
},
options => {
snapshots => "0",
compress => "0",
# This is expressed as an array
exclude => 'undef',
},
);
如果在Perl中曾经使用过goto LABEL
语句,那就是它。
do {
START: # could also go right before the "do"
...
if (...) {
warn "Configuration exists. Start over.\n";
goto START;
}
} while (...);
为什么你有3个elsif
s, else
简单的做法?
我的意思是,他们只测试什么样的关联正好相反if
测试。
if ($host eq '') {
...
} elsif ($host ne '') {
...
}
if ($config{$_}{host} ne $host) {
...
} elsif ($config{$_}{host} eq $host) {
...
}
if ($ping_obj->ping($host)) {
...
} elsif (! $ping_obj->ping($host)) {
...
}
我会使用普通的while
循环,而不是do{...}while(...)
循环。
do{
RESTART:
if(...){
goto RESTART;
}
}while(...);
VS
while(...){
if(...){
redo;
}
}
在此循环中,您只使用%config
的键来查找关联值,那么为什么不使用values %config
。
foreach (keys %config) {
if ($config{$_}{host} ne $host) {
last;
} elsif ($config{$_}{host} eq $host) {
warn "Configuration for $host already exists!\n";
}
}
VS
for( values %config ){
if( $_->{host} ne $host ){
...
} else {
...
}
}
如果您使用的是5.10.0或更高版本,则可以使用智能匹配( ~~
) ,这样可以更清楚地了解您正在测试的内容。
my @hosts = map{ $_->{host} } values %config;
if( $host ~~ @hosts ){
...
}
我不确定你为什么要使用do ... while
, while
看起来更自然。
一些说明:
$host eq ''
为真,则$host ne ''
必须为false。 根据定义。 $host
,我认为你不是,因为你将它存储在散列中,你应该把my $host
放在循环中,以限制范围。 一些技巧:
while ($config{$config_tag}{host} eq 'undef') {
print "Enter the hostname or IP of the ESXi server: ";
chomp(my $host = <STDIN>);
if ($host eq '') {
print "You must enter a hostname or IP address!\n";
redo;
} else {
# We need to catch duplicate configurations
my @host_list = map { $_->{host} } values %config
if ($host ~~ @host_list) {
warn "Configuration for $host already exists!\n";
redo;
}
}
if ($ping_obj->ping($host)) {
$config{$config_tag}{host} = $host;
} else {
print RED . "Ping test for \'$host\' failed" . RESET . "\n";
}
$ping_obj->close();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.