web-dev-qa-db-fra.com

Déclaration de commutateur Perl

Existe-t-il un moyen d'exécuter un bloc de code si aucun des blocs de cas ne correspond? Par exemple:

switch($a) {

  case // {}
  case // {}
  ...
  # DO SOMETHING IF NONE OF THE ABOVE CASES WERE MATCHED
}

else n'est pas ce que je recherche, car il s'applique uniquement au dernier bloc de cas.

17
snoofkin

Il y a toujours la commutation dans Perl 5.10, si vous l'exécutez bien sûr.

use feature qw(switch);

given($a){
  when(1) { print 'Number one'; }
  when(2) { print 'Number two'; }
  default { print 'Everything else' }
}
37
chambwez

Veuillez noter que use Switch sous n'importe quelle forme est obsolète car il est remplacé (et supprimé dans la prochaine version de Perl) par la propre forme d'instruction switch de Perl, qui est, comme déjà répondu:

use feature qw(switch);

given ($x)
{
when ('case1') { print 1; }
default {print 0; }
}

L'utilisation de la casse par défaut permet d'obtenir le résultat souhaité. N'oubliez pas non plus d'utiliser last si vous voulez que le commutateur cesse d'être évalué après qu'une condition est évaluée vraie.

11
cyber-guard

J'utilise généralement la construction de bloc ci-dessous qui est plus simple et n'a pas besoin d'importer quoi que ce soit.

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;
6
Swadhikar C

else est en effet ce que vous recherchez.

switch ( $n ) {
    case 1 { print "one\n" }
    case 2 { print "two\n" }
    else   { print "other\n" }
}

Ce qui précède afficherait "autre" pour $n=3 et "un" pour $n=1.

5
Tim

Cette déclaration renvoie Cas 2:

my $test = 'abcd';

print test($test);

sub test {
    for ($_[0]) {
        /ad/ && return 'Case 1';
        /bc/ && return 'Case 2';
        /c/ && return 'Case 3';
    }
}

Celui-ci retourne Cas:

my $test = 'abcd';
my $result;

for ($test) {
    /ad/ && do { $result = 'case 1' };
    /bb/ && do { $result = 'case 2' };
    /cd/ && do { $result = 'case 3' };
}

print $result;

Celui-ci Cas 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;

par défaut:

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;
3
Gordon Freeman

"Sinon, ce n'est pas ce que je recherche, car il ne s'applique qu'au dernier bloc de cas."

Tant que vous n'utilisez pas de transition:

use Switch 'fallthrough';

Tu es en sécurité.

Si vous atteignez la dernière instruction case, cela signifie qu'aucune des instructions case ci-dessus ne correspond aux critères. En d'autres termes (s'il n'y a pas d'interruption), l'instruction else n'est exécutée que si toutes les instructions case ne satisfont pas à leurs conditions.

3
Nylon Smile

Si vous avez seulement besoin de décider d'une affectation, utilisez l'opérateur ternaire ?:

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
1
Hans Ginzel

En supposant que vous utilisez use Switch , vous pouvez utiliser une clause else

1
Simon Whitaker

J'ai écrit et utilisé ces trois commutateurs de sous-programmes Perl et je les trouve très utiles.

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;
}
0
P.Pscholka