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

问题描述 投票:0回答:2

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

但我想做这样的事情:

perl myScript mandatoryArgument1 -optionalArgument1=someValue

我希望脚本在缺少 CommandArgument1 时抛出错误。这怎么办?

perl command-line-arguments getopt getopt-long
2个回答
7
投票

好的

Getopt::Long
没有这样的机制。它专门处理选项

但是,当它完成工作时,它会从

@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) {
    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
作用于非选项输入,但它无法检测到预期的输入在那里。

该模块确实允许在命令行的任何位置将参数与命名选项混合。请参阅文档中的带有其他参数的选项。所以你可以调用该程序作为

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


3
投票
我的方法

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 defined $file; [...] }
在这种情况下,选项 

--file

-f
 是强制性的。我检查 
$file
 是否已定义,否则我将中止执行并打印程序的帮助。

我不会将

--param=*value* 形式的 named

 输入参数与非命名参数混合在一起。
也就是说,您可以在调用 
@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
您必须将强制参数限制在固定位置(在我的示例中是问题中的第一个参数,但也可能是最后一个)。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.