如何在使用Getopt解析参数时允许未定义的选项?

19

如果我有一个命令行如下:

my_script.pl -foo -WHATEVER
我的脚本知道关于--foo,我想让 Getopt 设置变量 $opt_foo,但我不知道任何关于 -WHATEVER 的信息。我该如何告诉 Getopt 解析我已经告诉它的选项,并将其他参数存储在字符串变量或列表中?
一个例子:
use strict;
use warnings;

use Getopt::Long;

my $foo; 

GetOptions('foo' => \$foo); 

print 'remaining options: ', @ARGV;

然后,执行

perl getopttest.pl -foo -WHATEVER

会得到如下输出:

未知选项: whatever
剩余选项:
3个回答

23
你需要通过Getopt::Long::Configure("pass_through");来配置"pass_through"选项。这样它就支持实际的选项(例如以"-"开头且没有特殊的"--"分隔符来表示“真正”的选项)。以下是perldoc的引用:
- pass_through(默认值:禁用)
未知、模糊或提供无效选项值的选项将通过@ARGV传递,而不是标记为错误。这使得编写包装脚本成为可能,该脚本仅处理用户提供的命令行参数的一部分,并将其余选项传递给其他程序。
这是一个示例:
$ cat my_script.pl
#!/usr/local/bin/perl5.8 -w

use Getopt::Long;
Getopt::Long::Configure("pass_through");
use Data::Dumper;
my %args;
GetOptions(\%args, "foo") or die "GetOption returned 0\n";
print Data::Dumper->Dump([\@ARGV],["ARGV"]);

$ ./my_script.pl -foo -WHATEVER          
$ARGV = [
          '-WHATEVER'
        ];

1
啊哈,这就解释了为什么我没找到它... :) - Ether
4
我发现阅读perldoc网站上的某些不错选项,然后回到我那个陈旧的公司Perl安装程序时,发现我找到的完美选项需要一个flux capacitor,或至少需要升级CPAN模块,这让我感到非常恼火。 - DVK
1
你确定在5.8版本中没有pass_through吗?我刚刚查看了5.6.1的perldoc Getopt::Long(你以为你是史前时代的人;)),它是存在的。 - Zaid
@Zaid - 你说得完全正确!我没有完全正确地阅读POD,一直在寻找通过import配置的选项;而这个是通过特殊的Configure()调用完成的。我已经更新了我的答案。 - DVK
我刚刚向MooseX::Getopt队列添加了一个功能请求,以允许这样的配置:https://rt.cpan.org/Ticket/Display.html?id=58704(所以如果你喜欢它,请回复“我也是”):) - Ether

1

剩余的(未解析的)值不是只留在@ARGV中吗?如果您的额外内容以破折号开头,则需要使用--指示选项列表的结束:

#!/usr/bin/perl
use strict;
use warnings;
use Getopt::Long;
use Data::Dumper;

my $foo;
my $result = GetOptions ("foo"   => \$foo);
print Dumper([ $foo, \@ARGV ]);

然后调用:

my_script.pl --foo -- --WHATEVER

给出:

$VAR1 = [
          1,
          [
            '--WHATEVER'
          ]
        ];

PS. 在 MooseX::Getopt 中,来自命令行的“其余”选项被放置在extra_argv属性中作为一个数组引用 - 所以我建议进行转换!


如果它们看起来像选项,那么它们就不是。相反,类似于“未知选项:WHATEVER”的错误将被发出到标准错误流(STDERR)。 - Robert P
确实!哈哈,我也在问题中添加了这样的例子。 - Robert P

0

我认为这里的答案很遗憾,是“不行,没有一种使用Getopt::Long完全像您要求的方式,而不需要自己解析@ARGV。”然而,Ether有一个不错的解决方法。对于大多数人来说,任何类似选项的参数被捕获为错误都是一个特性。通常,您可以执行以下操作:

GetOptions('foo' => \$foo) 
    or die "Whups, got options we don't recognize!";

为了捕获/防止传递奇怪的选项,然后您可以纠正用户的使用。或者,您可以简单地通过并忽略它们。

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