如何在Perl中使用Getopt时对参数进行分组?

Laz*_*zer 1 perl command-line getopt command-line-arguments

对于我正在编写的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 = 
$
Run Code Online (Sandbox Code Playgroud)

Zai*_*aid 6

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

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


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

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

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

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

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

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

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

此示例完全等效于:

my $len = 0;
GetOptions ('length=i' => \$len);   # will store in $len
Run Code Online (Sandbox Code Playgroud)

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

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 ... }
Run Code Online (Sandbox Code Playgroud)