2010-11-12 82 views
1

对于我正在编写的perl脚本,可能会提供很多(〜50)的命令行选项。他们中的大多数是可选的,所以通话只会提供一些选项。如何在Perl中使用Getopt时对参数进行分组?

我正在使用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 = 
$ 

回答

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, 
); 

(请注意,这是一个坏主意,用$a$bsort以外的任何东西)。

+0

正如我在问题中提到的,我有大约50个,如果他们没有分组,很难跟踪他们。 – Lazer 2010-11-12 10:19:18

+1

@Lazer,那么你将不得不更好地解释“分组”的含义。 GetOptions不关心他们列出的顺序;以任何对你有意义的顺序列出它们。 – cjm 2010-11-12 10:27:14

6

这可能是一个好主意来存储你的选择在一个散而不是:

Getopt::Long : Storing options values in a hash


有时候,例如当有 很多选择,有一个单独的 变量它们每个都可以是 繁琐。 GetOptions()支持,作为 一个替代机制,存储 选项值在一个散列。

要获取此信息,必须将对散列 的引用作为第一个参数 传递给GetOptions()。对于在命令行上指定的每个选项 , 选项值将存储在 哈希中,并且选项名称为关键字。实际上未上 命令行中使用 选项将不会在 放散列,上换句话说, exists($h{option})(或defined())可以 被用来测试是否使用一个选项。 的缺点是,如果该计划下的使用 严格的运行,并使用$h{option}没有 测试与exists()defined() 第一警告将被 发行。

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

对于采用列表或哈希值的选项,它是 必要 为表示该情况 类型后附加一个@或%符号:

GetOptions (\%h, '[email protected]');  # 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 ... } 
+1

+1 - 除了其他原因,一旦你开始做任何复杂的开发,有单个变量的选项而不是散列,你可以作为一个整体传递给对象的构造函数是非常痛苦的。 – DVK 2010-11-12 17:03:23

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"; 
2

最直接的答案是使用的Getopt ::龙::配置,像这样:

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 
相关问题