-1

我正在使用 switch 语句来检查终端上提供的参数。如果最终用户提供,则提供的脚本工作正常

      $perl test.pl -help 

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

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

请建议!

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

2 回答 2

4

Switch是一个实验模块,不适合实际使用。5.10 引入了given/形式的 switch 语句when

顺便说一句,您可能希望查看Getopt::Long以更好地处理其中一些工作。

于 2013-04-24T21:25:27.280 回答
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;
}

如果我们设置@ARGVqw/ -link x y -web/,并使用 as 参数调用该 sub @ARGV,我们将得到以下输出:

arguments provided : -link x y -web

首先,我们来看-link。这导致我们将第四个元素放入@ARGV我们正在查看的变量中。这将保持-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();
  }
}

这就是它的完成方式。

于 2013-04-24T22:06:00.403 回答