无法使用perl switch语句对相同的子例程进行递归调用

时间:2013-04-24 21:06:00

标签: perl recursion switch-statement

我使用switch语句来检查终端上提供的参数。 如果最终用户提供

,则提供的脚本正常工作
      $perl test.pl -help 

但是当用户给出下面的选项时,子程序不会被递归调用。

      $perl test.pl -link abc -web test.com

Plz建议!

      use Switch;
      #perl test.pl -help
      #perl test.pl -link abc -web test.com

      sub CheckArgument {

       my ($argv)   = shift @_;
       local $\     = "\n";
       print "\$argv : $argv\n";

       switch($argv) {
                  case /-help/ {
                             print "Usage : $0 -link <link name> -web <website name>";
                             print "Usage : $0 -list_web_name";
                             exit;
                  }
                  case /-list_web_name/ {
                             print "Currently Support following site";
                             foreach (qw/abc/) {
                                        print "$_";
                              }
                             exit;
                   }
                  case /-link/ {
                             CheckArgument($ARGV[3]);
                  }
                  case /-web/ {
                             print "argument provided : @ARGV\n";       
                  }
                  default {
                             CheckArgument("-help");
                  }
        }
       }

2 个答案:

答案 0 :(得分:4)

Switch是一个不适合实际使用的实验模块。 5.10以given / when

的形式引入了一个switch语句

顺便说一下,您可能希望看一下Getopt::Long来更好地处理部分工作。

答案 1 :(得分:2)

首先,不推荐使用Switch源过滤器。请不要使用它。

这是一个没有递归的代码重写,可能更容易理解:

use 5.010;
sub CheckArgument {
  my $_ = shift;

  ARG: {
    if (/-help/) {
      say "Usage: $0 -link <link-name> -web <website-name>";
      say "Usage: $0 -list_web_name";
    } elsif (/-list_web_name/) {
      say "Currently supporting following sites:";
      say for qw/a b c/;
    } elsif (/-link/) {
      $_ = $ARGV[3];
      redo ARG;
    } elsif (/-web/) {
      say "arguments provided : @ARGV\n";       
    } else {
      $_ = "-help";
      redo ARG;
    }
  }
  exit;
}

如果我们将@ARGV设置为qw/ -link x y -web/,并以@ARGV作为参数调用该子,我们将获得以下输出:

arguments provided : -link x y -web

首先,我们来看-link。这导致我们将@ARGV中的第4个元素放到我们正在查看的变量中。这将在下一次迭代中保留-web,这将输出所有命令行参数。这种解析策略绝不健全。

当你有未经处理的参数时,比递归更好的是循环。如果您认识到交换机,请从arglist中删除交换机及其值。如果您不理解参数,请打印用法:

use 5.010;
# I use 5.010 for the C<say> function, but if we're already using it,
# we could just as well use given/when. Wouldn't make it much prettier.
sub ProcessArguments {
  ARG: while (@_) {
    my $_ = shift;
    if (/\A-?-list_web_name\z/) {
      say "Currently supporting following sites:";
      say for qw/a b c/;
    } elsif (/\A-?-link\z/) {
      my $link_name = shift;
      shift() =~ /\A-?-web\z/ or do { Usage(); exit };
      my $website_name = shift;
      do_something_with($link_name, $website_name);
    } elsif (/\A-?-web\z/) {
      my $website_name = shift;
      shift() =~ /\A-?-link\z/ or do {Usage(); exit };
      my $link_name = shift;
      do_something_with($link_name, $website_name);
    } else {
      Usage();
      exit;
    }
  }
}
sub Usage {
  say "Usage: $0 -link <link-name> -web <website-name>";
  say "Usage: $0 -list_web_name";
}

哦,这个糟糕的样板,无休止的重复。如果有人已经写了一些已经为我们提供选择的东西,那不是很好吗?比如CPAN模块?

use Getopt::Long;
use 5.010;
sub ProcessArguments {
  my $list_web_name;
  my $help;
  my ($link_name, $website_name);
  GetOptions
    'list-web-name' => \$list_web_name,
    'help'          => \$help,
    'link=s'        => \$link_name,
    'web=s'         => \$website_name;
  if ($help) {
      Usage();
  } elsif ($list_web_name) {
      say "Currently supporting following sites:";
      say for qw/a b c/;
  } elsif (defined $link_name and defined $website_name) {
      do_something_with($link_name, $website_name);
  } else {
      Usage();
  }
}

这就是它的完成方式。