28

在 Perl 5 中是否有一种巧妙的方式来制作 case 或 switch 语句?在我看来,他们应该包括一个版本 6 的开关..

我需要在脚本中使用这种控制结构,而且我听说您可以导入“开关模块”。但是如何在没有导入的情况下实现它以最大限度地减少依赖关系并获得可移植性?

4

5 回答 5

58

如果您使用的是 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; }
}

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

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

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

$string =~ /^abc/ ? $abc     = 1  :
$string =~ /^def/ ? $def     = 1  :
$string =~ /^xyz/ ? $xyz     = 1  :
                    $nothing = 1;

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

或替代语法

use Switch 'Perl6';

given ($string) {  
    when /^abc/ { $abc     = 1; }
    when /^def/ { $def     = 1; }
    when /^xyz/ { $xyz     = 1; }
    default     { $nothing = 1; }
}
于 2009-05-10T03:37:02.623 回答
20

Programming Perl 中的建议是:


for ($string) {
    /abc/ and do {$abc    = 1; last;};
    /def/ and do {$def    = 1; last;};
    /xyz/ and do {$xyz    = 1; last;};
    $nothing = 1;
}
于 2009-05-10T03:59:09.217 回答
10

只是对在答案中多次提到的核心Switch模块的简短评论。有问题的模块依赖于源过滤器。除其他外,这可能会导致报告错误的错误行。太糟糕了,以至于没有一个核心开发人员真正记得或关心记住为什么它首先被接受到 perl 核心中。

此外,Switch.pm 将是第一个从 perl 核心中删除的 Perl 模块。perl 的下一个主要版本 5.12.0 仍将包含它,尽管带有弃用警告。如果您从 CPAN 显式安装 Switch.pm,该弃用警告将消失。(你得到你想要的。)在下一个版本 5.14 中,Switch.pm 将从核心中完全删除。

于 2009-05-12T07:23:41.943 回答
9

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

my $switch = {
  'case1' => sub { print "case1"; },
  'case2' => sub { print "case2"; },
  'default' => sub { print "unrecognized"; }
};
$switch->{$case} ? $switch->{$case}->() : $switch->{'default'}->();
于 2009-05-11T15:36:47.153 回答
0
print("OK : 1 - CANCEL : 2\n");
my $value = <STDIN>;
SWITCH: {
    ($value == 1) && last(SWITCH);
    ($value == 2) && do {print("Cancelled\n"); exit()};
    print("??\n");
}
于 2013-08-07T20:01:04.940 回答