【问题标题】:Manipulating flag type in GetOptions from Getopt::Long从 Getopt::Long 操作 GetOptions 中的标志类型
【发布时间】:2015-03-18 20:06:34
【问题描述】:

如果GetOptions 中默认启用标志,有没有办法关闭它们?

这就是我想要的:

  • -verbose 0 关闭冗长
  • -verbose 1 开启详细程度
  • -verbose 开启详细程度

当前代码(来自Getopt::Long):

use Getopt::Long;
my $data = "file.dat";
my $length = 24;
my $verbose = 1;
GetOptions ("length=i" => \$length,   # numeric
            "file=s"   => \$data,     # string
            "verbose"  => \$verbose)  # flag
or die("Error in command line arguments\n");

【问题讨论】:

    标签: perl getopt


    【解决方案1】:

    这不是您描述的方式,而是documentation 描述了由感叹号指定的“否定选项”,可以让您这样做:

    my $verbose = 1; # default on
    GetOptions ('verbose!' => \$verbose);
    

    这允许--verbose(设置为1)或--noverbose(设置为0)。

    【讨论】:

      【解决方案2】:

      Getopt::Long 文档中的 Summary of Option Specifications 表示您几乎可以使用:

      #!/usr/bin/env perl
      use strict;
      use warnings;
      
      use Getopt::Long;
      my $data = "file.dat";
      my $length = 24;
      my $verbose = 1;
      GetOptions ("length=i"  => \$length,   # numeric
                  "file=s"    => \$data,     # string
                  "verbose:i" => \$verbose)  # optional integer
      or die("Error in command line arguments\n");
      
      # Debugging/testing
      print "Verbose = $verbose\n";
      print "Options:\n";
      for my $opt (@ARGV) { print "    $opt\n"; }
      

      :表示取值可选,i表示取整数。

      示例运行(我将脚本称为gol.pl):

      $ perl gol.pl
      Verbose = 1
      Options:
      $ perl gol.pl --verbose 0
      Verbose = 0
      Options:
      $ perl gol.pl --verbose=0
      Verbose = 0
      Options:
      $ perl gol.pl --verbose 1
      Verbose = 1
      Options:
      $ perl gol.pl --verbose gooseberry
      Verbose = 0
      Options:
          gooseberry
      $ perl gol.pl --verbose
      Verbose = 0
      Options:
      $
      

      顶部有一个'几乎'。正如ThisSuitIsBlackNot 正确points out,当参数被省略时,这会将$verbose 设置为零,这不是您想要的。

      你的界面很奇怪。你确定你不会更好:

      --verbose    # Enables verbose mode
      --noverbose  # Disables verbose mode
      

      然后您可以使用"verbose!" 来处理它。另外,由于verbose模式默认开启,所以真的不需要支持--verbose;让--verbose 0 将其关闭或--noverbose 是有意义的,并且可能指向允许--verbose 9 进行额外的详细说明等。您需要考虑您的设计是否真正合适。

      【讨论】:

      • 这是我所拥有的,但gol.pl --verbose 会将$verbose 设置为 0,而不是 OP 要求的 1。
      • @ThisSuitIsBlackNot:好点——我在“gooseberry”测试中错过了这一点。我会添加一些注释。
      • 感谢您的回答。 -noverbose 选项满足我的需要。
      【解决方案3】:

      这可能有点过于复杂,但您可以将optional valuecustom subroutine 结合使用:

      use strict;
      use warnings;
      use 5.010;
      
      use Getopt::Long;
      
      sub make_handler {
          my $verbose = shift;
      
          return sub {
              my ($opt_name, $opt_value) = @_;
      
              die "$opt_name must be 0 or 1" if $opt_value !~ /^(?:0|1)?$/;
      
              if ($opt_value eq '') {
                  $$verbose = 1;
              }
              else {
                  $$verbose = $opt_value;
              }
          }
      }
      
      my $verbose = 1;
      my $handler = make_handler(\$verbose);
      
      GetOptions("verbose:s"  => $handler) or die "Error in command line arguments";
      
      say $verbose;
      

      输出:

      $ ./foo 
      1
      $ ./foo --verbose
      1
      $ ./foo --verbose 0
      0
      $ ./foo --verbose 1
      1
      $ ./foo --verbose bar
      verbose must be 0 or 1 at ./foo line 15.
      Error in command line arguments at ./foo line 29.
      

      请注意,我使用闭包来避免全局变量,因为Getopt::Long 不会对自定义子例程的返回值做任何事情,并且不允许您传入要设置的变量。

      【讨论】:

      • 感谢您的回答。 -noverbose 选项满足我的需要。
      • @Jean 这更有意义。 FWIW,我从来没有见过默认情况下很冗长的命令行程序......通常有一个 --verbose 选项来显示比正常输出更多的输出和一个 --quiet 选项来显示 no输出。对于命令行选项,您通常应遵循最小意外原则并遵循通用约定。
      • 详细只是一个例子。我正在做其他事情。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-07-05
      • 2020-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多