Perl Switch Statement
Is there any way to run a block of code if none of the case blocks were matched? For instance:
switch($a) {
case // {}
case 开发者_如何学Python// {}
...
# DO SOMETHING IF NONE OF THE ABOVE CASES WERE MATCHED
}
else
is not what I'm looking for, since it applies only to the last case block.
There's always the switching in Perl 5.10, if you're running it of course.
use feature qw(switch);
given($a){
when(1) { print 'Number one'; }
when(2) { print 'Number two'; }
default { print 'Everything else' }
}
Please note that use Switch
in any form is deprecated as it is being replaced (and removed in the next perl release) by perl's own form of switch statement, which is, as already answered:
use feature qw(switch);
given ($x)
{
when ('case1') { print 1; }
default {print 0; }
}
Using default case achieves the outcome you want. Also don't forget to use last
if you want the switch to stop being evaluated after one condition is evaluated true.
I usually use the below block construct which is more simple and no need to import anything.
SWITCH: {
if($key =~ /^abc/) { $key = "key starts with abc"; last SWITCH; } # 'last' breaks the 'SWITCH' block
if($key =~ /^def/) { $key = "key starts with def"; last SWITCH; }
if($key =~ /^ghi/) { $key = "key starts with ghi"; last SWITCH; }
$key = "Default value";
}
print $key;
else
is indeed what you are looking for.
switch ( $n ) {
case 1 { print "one\n" }
case 2 { print "two\n" }
else { print "other\n" }
}
The above would output "other" for $n=3
and "one" for $n=1
.
This statement return Case 2:
my $test = 'abcd';
print test($test);
sub test {
for ($_[0]) {
/ad/ && return 'Case 1';
/bc/ && return 'Case 2';
/c/ && return 'Case 3';
}
}
This one return Case 3:
my $test = 'abcd';
my $result;
for ($test) {
/ad/ && do { $result = 'case 1' };
/bb/ && do { $result = 'case 2' };
/cd/ && do { $result = 'case 3' };
}
print $result;
This one Case 2:
my $test = 'abcd';
my $result;
for ($test) {
/ad/ && do { $result = 'case 1'; last };
/bc/ && do { $result = 'case 2'; last };
/cd/ && do { $result = 'case 3'; last };
}
print $result;
Default:
my $test = 'abcd';
my $result;
for ($test) {
/aa/ && do { $result = 'case 1'; last };
/bb/ && do { $result = 'case 2'; last };
/cc/ && do { $result = 'case 3'; last };
$result = 'Default';
}
print $result;
"else is not what I'm looking for, since it applies only to the last case block."
As long as you are not using fall-through:
use Switch 'fallthrough';
You are safe.
If you reach the last case statement it means none of the case statements above it matched the criteria. In other words (if there is no fall-through) the else statement is only executed if all case statements fail to satisfy their conditions.
Assuming you're using use Switch
, you can use an else
clause
If you only need to decide an assignment use the ternary operator ?:
die "Expecting name of the system (reise/synpac/vias) as parameter.\n"
unless $_ = shift;
@opt{qw/Name Code Id UID/} =
/^\s*rei(?:se)?\s*$/i ? qw/ CEP REI 80 ipcp_rei / :
/^\s*syn(?:pac)?\s*$/i ? qw/ SYNPAC SYNPAC 67 ipcp_sym / :
/^\s*vias?\s*$/i ? qw/ VIAS VIAS 68 ipcp_via / :
do { die "Unknown system ‘$_’.\n"; }; # or default values
No need for feature.
Is perlcritic safe. I have used this with 20+ options after converting from an else-if chain.
my $key = 'fruity'; # User chosen value
my %code_ref = (
apple => sub { print("Apple\n"); },
pear => sub { my_other_code(); },
orange => sub { my_still_other_code(); },
);
if ( exists $code_ref{$key} ) {
$code_ref{$key}->();
}
else { # Default case
print STDERR "$0: unknown option '$key'\n";
}
I wrote and use these three Perl subroutine switches and find them very useful.
sub switchOne($){ # standard switch
my($prefix,$testVal,@caseVals)=@_;
$s=0;
while($s<scalar(@caseVals)){
if($testVal eq $caseVals->[$s]){
return $prefix."_".$testVal;
}
$s++;
}
return $prefix."Not";
}
sub switchTwo($){ # test for 2 conditions switch = mapping x & Y
my($prefix,$testVal1,$testVal2,@caseVals1,@caseVals2)=@_;
$s=0;
while($s<scalar(@caseVals)){
if($testVal1 eq $caseVals1->[$s] && $testVal2 eq $caseVals2->[$s]){
return $prefix."_".$testVal1;
}
$s++;
}
return $prefix."Not";
}
sub switchRange($){ # test for range switch
my($prefix,$testVal1,@caseVals1,@caseVals2)=@_;
$s=0;
while($s<scalar(@caseVals)){
if($testVal > $caseVals->[$s]&&$testVal < $caseVals2->[$s]){
return $prefix."_".($s+1);
}
$s++;
}
return $prefix."Not";
}
############# here is the calling code
$prefix="case";
@cases=(1,12,3,45,5,61,7,8,9,10); # cases to test against / quote strings
$case=&switchOne($prefix,$testvariable,\@cases);
# prefix must be different for each switch call for different labels
#duplicate labels can cause problems
while($case ne ""){
# initialization common code block
goto $case;
case_1: # cases in array
#code
last;
case_12:
# code
last;
case_61:
last;
case_7:
last;
case_8:
last;
case_9:
last;
case_10:
last;
caseNot:
# no match comes here
#code
last;
}
# here is a dbl variable matching call example
# prefix can be in the call quoted
# both cases must be true to get a match
$case=&switchTwo("intrsctn",$test1,$test2,\@cases1,\@cases2);
while($case ne ""){
# initial code as desired
goto $case;
intrsctn_1:
# code
last;
# as many labels as cases
intrsctnNot:
last;
}
# here is a switch example to test for a variable in a range (between)
$case=&switchRange("thscase",$testvariable,\@cases1,\@cases2);
while($case ne ""){
goto $case;
thscase_1: # this returns the array index +1 on the prefix
# code
last;
# as many labels as cases
thscaseNot:
# N must be uppercase
last;
}
精彩评论