1

对于我正在编写的 perl 脚本,可以提供很多(约 50 个)命令行选项。它们中的大多数是可选的,因此调用将只提供一些选项。

我正在使用Getopt::Long,但它不允许我GetOptions多次使用。结果,我必须在一次GetOptions调用中使用所有命令行选项。

有没有什么好方法可以在使用时对选项进行分组GetOptions

$ cat test.pl
use strict;
use warnings;
use Getopt::Long;

my ($a, $b, $c, $d);

GetOptions ('a=s' => \$a, 'b=s' => \$b);
GetOptions ('c=s' => \$c, 'd=s' => \$d);

print "a = $a\nb = $b\nc = $c\nd = $d\n";

$ perl test.pl -a=AA -b=BB -c=CC -d=DD
Unknown option: c
Unknown option: d
Use of uninitialized value in concatenation (.) or string at test.pl line 10.
Use of uninitialized value in concatenation (.) or string at test.pl line 10.
a = AA
b = BB
c = 
d = 
$
4

4 回答 4

6

将您的选项存储在哈希中可能是个好主意:

请参阅Getopt::Long:将选项值存储在哈希中


有时,例如当有很多选项时,为每个选项设置一个单独的变量可能会很麻烦。GetOptions()作为一种替代机制,支持将选项值存储在哈希中。

为此,必须将对哈希的引用作为第一个参数传递给GetOptions(). 对于在命令行上指定的每个选项,选项值将存储在以选项名称作为键的散列中。命令行上实际未使用的选项不会放入哈希中,换句话说, exists($h{option})(或defined())可用于测试是否使用了选项。缺点是如果程序在 use strict 下运行并且在未使用or 先$h{option}测试的情况下使用,则会发出警告。exists()defined()

my %h = ();
GetOptions (\%h, 'length=i');       # will store in $h{length}

对于采用列表或哈希值的选项,有必要通过在类型后附加 @ 或 % 符号来表明这一点:

GetOptions (\%h, 'colours=s@');     # will push to @{$h{colours}}

为了使事情更复杂,哈希可能包含对实际目的地的引用,例如:

my $len = 0;
my %h = ('length' => \$len);
GetOptions (\%h, 'length=i');       # will store in $len

这个例子完全等同于:

my $len = 0;
GetOptions ('length=i' => \$len);   # will store in $len

任何混合都是可能的。例如,最常用的选项可以存储在变量中,而所有其他选项都存储在哈希中:

my $verbose = 0;                    # frequently referred
my $debug = 0;                      # frequently referred
my %h = ('verbose' => \$verbose, 'debug' => \$debug);
GetOptions (\%h, 'verbose', 'debug', 'filter', 'size=i');
if ( $verbose ) { ... }
if ( exists $h{filter} ) { ... option 'filter' was specified ... }
于 2010-11-12T10:31:36.083 回答
2

最直接的答案是像这样使用 Getopt::Long::Configure :

use strict;
use warnings;
use Getopt::Long;

my ($a, $b, $c, $d);

Getopt::Long::Configure( qw(pass_through) );
GetOptions ('a=s' => \$a, 'b=s' => \$b);

Getopt::Long::Configure( qw(no_pass_through) );
GetOptions ('c=s' => \$c, 'd=s' => \$d);

print "a = $a\nb = $b\nc = $c\nd = $d\n";

请注意,您应该确保您最后一次调用 GetOptions 应该配置为no_pass_through以确保您收到有关未知选项的警告。

% perl test_getop.pl -a AA -b BB -c CC -d DD -e EE
Unknown option: e
a = AA
b = BB
c = CC
d = DD
于 2011-06-08T17:57:37.773 回答
1

有什么问题:

GetOptions(
  'a=s' => \$a,
  'b=s' => \$b,
  'c=s' => \$c,
  'd=s' => \$d,
);

或者,如果它们都很短,你可以这样做:

GetOptions(
  'a=s' => \$a,   'b=s' => \$b,
  'c=s' => \$c,   'd=s' => \$d,
);

(请注意,除了比较之外,使用$aand是一个坏主意。)$bsort

于 2010-11-12T10:08:26.943 回答
0

通常,数组在传递给函数之前会被展平为单个列表,尽管某些函数会覆盖此行为。使用它,您可以定义选项组数组并将数组列表传递给 GetOptions。

use strict;
use warnings;
use Getopt::Long;

my ( $opt_a, $opt_b, $opt_c, $opt_d );

my @opt_group_1 = ( 'a=s' => \$opt_a, 'b=s' => \$opt_b );
my @opt_group_2 = ( 'c=s' => \$opt_c, 'd=s' => \$opt_d );
GetOptions( @opt_group_1, @opt_group_2 );

print "a = $opt_a\nb = $opt_b\nc = $opt_c\nd = $opt_d\n";

您可以将其与在哈希中存储值结合起来,以防止必须创建大量的选项变量,正如 Zaid 提到的那样。

use strict;
use warnings;
use Getopt::Long;

my @opt_group_1 = ( 'a=s', 'b=s' );
my @opt_group_2 = ( 'c=s', 'd=s' );

my %opt;

GetOptions( \%opt, @opt_group_1, @opt_group_2 );

print "a = $opt{a}\nb = $opt{b}\nc = $opt{c}\nd = $opt{d}\n";
于 2010-11-12T18:46:56.073 回答