如何将强制和可选命令行参数传递给perl脚本?

时间:2016-05-26 06:46:25

标签: perl command-line-arguments getopt getopt-long

我使用Getopt :: Long将选项传递给我的Perl脚本。

但我想做这样的事情:

perl myScript mandatoryArgument1 -optionalArgument1=someValue

如果missingArgument1丢失,我希望脚本抛出错误。怎么办呢?

2 个答案:

答案 0 :(得分:5)

Getopt::Long没有相应的机制。具体而言processes options

但是,一旦完成其工作,这些选项将从@ARGV中删除,然后您可以检查是否存在预期参数。请参阅第二部分,但我想首先提出另一种方法:将这些参数命名,然后Getopt将处理它们。

然后很容易检查它们是否已提交。例如

use warnings;
use strict;
use feature 'say';
use Getopt::Long;

my $mandatoryArg;
my $opt;

# Read command-line arguments, exit with usage message in case of error
GetOptions( 'name=s' => \$mandatoryArg, 'flag' => \$opt )
    or usage(); 

if (not defined $mandatoryArg) {
    # print specific message, the generic usage message, and exit
    say STDERR "Argument 'name' is mandatory";
    usage();
}

# The program goes now. Value for $opt may or may have not been supplied

sub usage {
    say STDERR "Usage: $0 ...";   # full usage message
    exit;
}

因此,如果命令行中未给出--name string$mandatoryArg将保持未定义状态并退出程序。该变量不需要默认值,因为它是必需的。

参数检查和处理通常涉及更多,这是Getopt闪耀的时候。

问题中的mandatoryArgument1没有提供名称。虽然Getopt可以act on a non-option input,但它无法检测到预期的

该模块允许在命令行的任何位置混合带有命名选项的参数。请参阅文档中的Option with other arguments。所以你可以调用程序

script.pl --opt1 value1 unnamed_arg --opt2 value2

但我建议用户在选项后提供它们。

然后,在GetOptions完成其工作后,@ARGV将包含字符串unnamed_arg,您可以获取它(或发现它不在那里)。 GetOptions对命名选项的处理与上述相同。

my ($var1, $var2, $flag);

GetOptions('opt1=s' => \$var1, 'opt2=i' => \$var2, 'f' => \$flag)
    or usage(); 

# All supplied named options have been collected, all else left in @ARGV
# Read the remaining argument(s) from @ARGV, or exit with message

# This can get far more complicated if more than one is expected
my $mandatoryArg1 = shift @ARGV || do {
    say STDERR "Mandatory argument (description) is missing";
    usage();
};

@ARGV获取命名参数后,您必须手动处理Getopt。如果存在多个这样的参数,则必须严格遵守它们在命令行上的相对位置,并且可能很难检查用户是否可能混淆了它们的顺序。

虽然所有可能的模块(如Getopt)都存在,但我们不必这样做。

使用'<>'

的“名称”设置看似不是选项的输入操作
Getoptions( 'opt=s' => \$var, ..., '<>' => \&arg_cb );

sub arg_cb { say "Doesn't look like an option: $_[0]" }

只有在看到非选项参数的情况下才会调用子arg_cb

答案 1 :(得分:2)

我使用Getopt::Long的方法:

sub help { print "Some help"; exit }

sub main {
    GetOptions(
        'file|f=s'   => \( my $file = undef ),
        'tag|t=s'    => \( my $tag = undef ),
        'help|h'     => \( my $printHelp = undef ),
    );

    help() if $printHelp;
    help() unless $file;

[...]

}

在这种情况下,选项--file-f是必需的。我检查是否定义了$file,否则我中止执行打印程序的帮助。

我不会将{em>命名的输入参数以--param=*value*的形式与无命名参数混合。 也就是说,您可以在调用@ARGV之前操作Getopt::Long并将其配置为执行您所要求的操作,但为用户混合两种类型的输入参数 philosophy 会让人感到困惑你的剧本。

#!/usr/bin/env perl
use strict;
use warnings;
use feature qw{say};
use Carp;
use Getopt::Long;    

sub main {    
    my $firstParam = shift @ARGV;
    croak "Mandatory parameter not given"
        if (!$firstParam || $firstParam =~ /^-/);

    GetOptions(
        'file|f=s'   => \( my $file = undef ),
        'tag|t=s'    => \( my $tag = undef ),
    );


    say 'Mandatory: ', $firstParam;
    say 'Optional $file: ', $file if $file;
    say 'Optional $tag: ', $tag if $tag;
}

main();

您可以将其称为./test.pl mandatory -f file -t tag

Mandatory: mandatory                                                                                        
Optional $file: file                                                                                      
Optional $tag: tag  

你必须将强制性参数限制在一个固定的位置(在我的例子中,问题中的第一个,但它也可能是最后一个)。