在更新的Getopt::Long中,如何设置可选参数的默认值?

4
在Perl的Getopt::Long 2.39版本中,我可以使用
use Getopt::Long qw( :config gnu_getopt );
GetOptions(
   \my %opts, 
   "codon-view|c:20",    # Optional value, default 20
   "consensus|C:50", 
   ...
)

为了表明如果我使用-c,默认值将会是20并放在%opts哈希表中的codon-view键下,当使用-c但没有显式指定它的值时。另一方面,如果没有提供-c--codon-view,则在%opts哈希表中不会存储任何值。

在2.48版本中,这种方法已经不再适用了,在Getopt::Long文档中也没有找到相关说明。

$ perl -E'
   use Getopt::Long qw( :config gnu_getopt );
   say $Getopt::Long::VERSION;
   GetOptions(\my %opts, "codon-view|c:20");
   say $opts{"codon-view"} // "[undef]"
' -- -c
2.39
20

$ perl -E'
   use Getopt::Long qw( :config gnu_getopt );
   say $Getopt::Long::VERSION;
   GetOptions(\my %opts, "codon-view|c:20");
   say $opts{"codon-view"} // "[undef]"
' -- -c
2.48
[undef]

我该如何实现旧有的行为?
帮帮我!

你确定这在2.39版本中可行吗?回溯到2000年发布的2.24版本,带有值选项的文档一直显示形式为tag=stag:i而不是tag:20的选项规范。 - ThisSuitIsBlackNot
我已经修改了帖子以包含这个。你得到的与我的行为相匹配。只有当给出-c--codon-view而没有值时,行为才会在2.39和2.48之间发生变化。此外,在FindOption中也有一些更改,这些更改涉及到gnu_getopt在这两个版本之间的差异。 - rocky
1
@ThisSuitIsBlackNot,搜索 : number - ikegami
1
这是在2.48中引入的更改。我不确定,但我认为这是无意中完成的,因此我提交了一个错误报告 - ikegami
4个回答

5

这是在2.48中引入的更改。

$ perl -E'
   use Getopt::Long qw( :config gnu_getopt );
   say $Getopt::Long::VERSION;
   GetOptions(\my %opts, "codon-view|c:20");
   say $opts{"codon-view"} // "[undef]"
' -- -c
2.47
20

$ perl -E'
   use Getopt::Long qw( :config gnu_getopt );
   say $Getopt::Long::VERSION;
   GetOptions(\my %opts, "codon-view|c:20");
   say $opts{"codon-view"} // "[undef]"
' -- -c
2.48
[undef]

我不确定,但我认为这是无意中完成的,所以我提交了一个错误报告


use Getopt::Long qw( :config gnu_getopt );

是缩写词,简称为。
use Getopt::Long qw( :config gnu_compat bundling permute no_getopt_compat );

你对使用gnu_compat有多少投入?
$ perl -E'
   use Getopt::Long qw( :config gnu_getopt );
   say $Getopt::Long::VERSION;
   GetOptions(\my %opts, "codon-view|c:20");
   say $opts{"codon-view"} // "[undef]"
' -- -c
2.48
[undef]

$ perl -E'
   use Getopt::Long qw( :config gnu_compat bundling permute no_getopt_compat );
   say $Getopt::Long::VERSION;
   GetOptions(\my %opts, "codon-view|c:20");
   say $opts{"codon-view"} // "[undef]"
' -- -c
2.48
[undef]

$ perl -E'
   use Getopt::Long qw( :config bundling permute no_getopt_compat );
   say $Getopt::Long::VERSION;
   GetOptions(\my %opts, "codon-view|c:20");
   say $opts{"codon-view"} // "[undef]"
' -- -c
2.48
20

gnu_compat控制--opt=的允许性及其作用。如果没有gnu_compat,则--opt=会出错。使用gnu_compat--opt=将会给出选项opt和空值。这是GNU getopt_long()的处理方式。

因此,如果您希望--codon-view=将零赋值给$opts{"codon-view"},请使用以下命令:

use Getopt::Long qw( :config bundling permute no_getopt_compat );

替代


use Getopt::Long qw( :config gnu_getopt );

由于这是一个可用性问题,我需要要求用户进行实验。目前我所做的是使用复制到模块中的2.39代码。根据您的说法,我想我可以将版本增加到2.47左右。 - rocky
再看一遍。我的解决方案不会影响您的任何用户。它只是使 --opt= 停止抛出错误。 - ikegami
看起来 gnu_compat 的文档是错误的。perl -MGetopt::Long=:config,gnu_compat -E'GetOptions(\%opts, "foo:1") or die; say "<$opts{foo}>"' -- --foo= 输出 <0>;移除 gnu_compat 则输出 <1>(而不是报错)。 - ThisSuitIsBlackNot
@ThisSuitIsBlackNot,如果没有“gnu_compat”选项,它会失败。/// Getopt::Long 的测试套件非常缺乏。 - ikegami
@ikegami 刚刚检查了一下。没错,就像你说的那样可以工作。这应该没问题。谢谢。 - rocky

3
在调用GetOptions()之前设置默认值。如果在命令行上未提供选项,则不会覆盖默认值。
$ perl -MGetopt::Long -E '$c=20;GetOptions("c=i"=>\$c); say $c' -- -c 14
14

$ perl -MGetopt::Long -E '$c=20;GetOptions("c=i"=>\$c); say $c' --
20

Getopt::Long 文档中有一个简单的示例


我想我之前的行为描述可能不够清晰。如果没有给出 -c 参数,那么该键就不在哈希表中。只有当设置了 -c 参数时,该键的值才有默认值。我会编辑我的问题以反映这一点。 - rocky

1

这里还有另一种可能但不太好的解决方案:包含Getopt::Long.pm的副本,它只有一个文件,但我已将包命名空间更改为其他名称,例如MyPackage :: GetoptLong。

这不是一个理想的答案,但如果您需要保持兼容性并且没有更好的ikegami解决方案,那么请记住这个方案。


0

我喜欢将我的选项分配给一个哈希表。

GetOptions(\ my %opt,
    'codon-view|c:i',
);

if ( exists $opt{'codon-view'} ) {
    print "User triggered '-c' flag\n";
    $opt{'codon-view'} ||= 20;
    printf( "codon-view: %d\n", $opt{'codon-view'} );
}

现在,如果用户运行 ./your-app -c,并且没有参数,$opt{c} 键将被创建,但其值为 undef,因此您必须检查它是否已经被触发了 exists||= 运算符只会在左侧是 falsey (通常是 undef)时才将右侧赋值给左侧。需要注意的是,如果有人执行 -c 0,它将会分配默认值...但我假设 0 可能是您的标志的不良参数。

很抱歉我没有完全报告我的情况。首先,是的,我使用选项哈希。此外,我使用 use Getopt::Long qw(config gnu_getopt);。当在 use 语句中未指定 gnu_getopt 时,您的示例确实有效。但是,当它被指定时,您的示例就不再起作用了。而且,它有点繁琐,并且在两个地方放置了 codon-view|c:20 的内容。如果我们可以解决指定 gnu_getopt 时的问题,如果找不到更好的解决方案,我会接受这个解决方案。 - rocky

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接