【问题标题】:Perl Switch StatementPerl 切换语句
【发布时间】:2011-06-22 14:22:37
【问题描述】:

如果没有匹配的案例块,有什么方法可以运行代码块?例如:

switch($a) {

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

else 不是我要找的,因为它只适用于最后一个 case 块。

【问题讨论】:

    标签: perl switch-statement case conditional-statements


    【解决方案1】:

    不需要功能

    perlcritic 安全吗。从 else-if 链转换后,我已将其与 20 多个选项一起使用。

    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";
    }
    

    【讨论】:

      【解决方案2】:

      我编写并使用了这三个 Perl 子程序开关,发现它们非常有用。

      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;
      }
      

      【讨论】:

        【解决方案3】:

        此语句返回案例2

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

        这个返回案例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;
        

        这个案例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;
        

        默认

        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;
        

        【讨论】:

          【解决方案4】:

          我通常使用下面的块结构,它更简单,不需要导入任何东西。

          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;
          

          【讨论】:

            【解决方案5】:

            如果您只需要决定分配,请使用三元运算符?:

            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
            

            【讨论】:

              【解决方案6】:

              请注意,任何形式的 use Switch 都已被弃用,因为它正在被 perl 自己的 switch 语句形式替换(并在下一个 perl 版本中删除),正如已经回答的那样:

              use feature qw(switch);
              
              given ($x)
              {
              when ('case1') { print 1; }
              default {print 0; }
              }
              

              使用默认大小写可以达到您想要的结果。如果您希望在一个条件被评估为真后停止评估开关,也不要忘记使用last

              【讨论】:

              • 请注意,given/when 后来被认为是实验性的。当然,您可以通过添加“no warnings 'experimental';”来消除警告。陈述。见perldoc.perl.org/functions/given.html
              【解决方案7】:

              Perl 5.10 中总是有切换的,当然如果你正在运行它的话。

              use feature qw(switch);
              
              given($a){
                when(1) { print 'Number one'; }
                when(2) { print 'Number two'; }
                default { print 'Everything else' }
              }
              

              【讨论】:

              • 关于开关功能的完整文档:perldoc.perl.org/perlsyn.html#Switch-statements
              • 还需要根据您想要的语法在“使用”语句中包含版本号。
              • 由于 Perl 5.18 可能要添加 no warnings qw( experimental::smartmatch );
              • 这种方法开始听起来很糟糕。正如@rustyx 所说,不妨添加无警告。如果你这样做,也不妨 1) 添加use warnings qw( experimental::smartmatch ); 2) 还为 no warnings 添加 perl 评论家排除 ``` ## nocritic (some_policy) ```
              【解决方案8】:

              “else 不是我要找的,因为它只适用于最后一个 case 块。”

              只要你不使用fall-through:

              use Switch 'fallthrough';
              

              你很安全。

              如果您到达最后一个 case 语句,则意味着它上面的 case 语句均不符合条件。换句话说(如果没有失败),只有在所有 case 语句都不能满足它们的条件时才会执行 else 语句。

              【讨论】:

                【解决方案9】:

                else 确实是您要找的。​​p>

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

                上面将为$n=3 输出“other”,为$n=1 输出“one”。

                【讨论】:

                  【解决方案10】:

                  假设您使用的是use Switch,您可以使用else 子句

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多