在Perl 5中获取切换/案例行为

lur*_*rks 27 perl switch-statement

在Perl 5中是否有一种简洁的方法来制作case或switch语句?在我看来,他们应该在版本6上包含一个开关..

我在脚本中需要这个控制结构,我听说你可以导入一个"开关模块".但是如何在没有导入的情况下实现它以最小化依赖性并获得可移植性?

Cha*_*ens 57

如果您使用的是Perl 5.10,那么given/when它是一个switch语句(注意,它可以做的不仅仅是与正则表达式进行比较,请阅读链接的文档以了解它的全部潜力):

#or any of the dozen other ways to tell 5.10 to use its new features
use feature qw/switch/; 

given($string) {
    when (/^abc/) { $abc     = 1; }
    when (/^def/) { $def     = 1; }
    when (/^xyz/) { $xyz     = 1; }
    default       { $nothing = 1; }
}
Run Code Online (Sandbox Code Playgroud)

如果您使用的是Perl 5.8或更早版本,则必须使用if/ elsif/ else语句:

if    ($string =~ /^abc/) { $abc     = 1; }
elsif ($string =~ /^def/) { $def     = 1; }
elsif ($string =~ /^zyz/) { $xyz     = 1; }
else                      { $nothing = 1; }
Run Code Online (Sandbox Code Playgroud)

或嵌套条件运算符(?:):

$string =~ /^abc/ ? $abc     = 1  :
$string =~ /^def/ ? $def     = 1  :
$string =~ /^xyz/ ? $xyz     = 1  :
                    $nothing = 1;
Run Code Online (Sandbox Code Playgroud)

Core Perl(Switch)中有一个模块通过源过滤器为您提供虚假的switch语句,但我理解它很脆弱:

use Switch;

switch ($string) {
    case /^abc/ {
    case /^abc/ { $abc     = 1 }
    case /^def/ { $def     = 1 }
    case /^xyz/ { $xyz     = 1 } 
    else        { $nothing = 1 }
}
Run Code Online (Sandbox Code Playgroud)

或替代语法

use Switch 'Perl6';

given ($string) {  
    when /^abc/ { $abc     = 1; }
    when /^def/ { $def     = 1; }
    when /^xyz/ { $xyz     = 1; }
    default     { $nothing = 1; }
}
Run Code Online (Sandbox Code Playgroud)

  • 'when'是隐含的'~~'运算符,因此不仅允许正则表达式. (2认同)

Nat*_*man 17

Programming Perl中的建议是:


for ($string) {
    /abc/ and do {$abc    = 1; last;};
    /def/ and do {$def    = 1; last;};
    /xyz/ and do {$xyz    = 1; last;};
    $nothing = 1;
}
Run Code Online (Sandbox Code Playgroud)


tse*_*see 9

关于核心交换机模块的简短评论,已在答案中多次提及.有问题的模块依赖于源过滤器.除此之外,这可能导致报告错误的错误行.这是非常糟糕的,没有一个核心开发人员真正记得或关心为什么它首先被接受到perl核心.

此外,Switch.pm将是有史以来第一个从perl核心中删除的Perl模块.perl的下一个主要版本5.12.0仍将拥有它,尽管有弃用警告.如果您从CPAN明确安装Switch.pm,那么弃用警告将消失.(你得到了你要求的东西.)在下一个版本中,5.14,Switch.pm将完全从核心中删除.


jig*_*ggy 8

我喜欢的等效解决方案是调度表.

my $switch = {
  'case1' => sub { print "case1"; },
  'case2' => sub { print "case2"; },
  'default' => sub { print "unrecognized"; }
};
$switch->{$case} ? $switch->{$case}->() : $switch->{'default'}->();
Run Code Online (Sandbox Code Playgroud)

  • 更短:`($ switch - > {$ case} || $ switch - > {default}) - >()` (5认同)