如何将强制和可选的命令行参数传递给 perl 脚本?
How to pass both mandatory and optional command line arguments to perl script?
我正在使用 Getopt::Long 将选项传递给我的 Perl 脚本。
但我想做这样的事情:
perl myScript mandatoryArgument1 -optionalArgument1=someValue
我希望脚本在缺少 mandatoryArgument1 时抛出错误。如何做到这一点?
我对 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
,否则我中止执行打印程序的帮助。
我不会将 named 形式的 --param=*value*
输入参数与无命名参数混合使用。
也就是说,您可以在调用 Getopt::Long
之前操作 @ARGV
并将其配置为执行您要求的操作,但是混合两种类型的输入参数 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
您必须将强制参数限制在固定位置(在我的示例中是问题中的第一个,但也可能是最后一个)。
好的 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) {
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: [=10=] ..."; # 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();
};
一旦 Getopt
选取了命名参数,您必须手动处理 @ARGV
。
如果有多个这样的参数,用户必须严格遵守它们在命令行上的预期相对位置,因为程序通常无法分辨什么是什么。所以一般情况下,用户在命令行上混淆顺序的错误是无法捕获的。
这会成为一个障碍,我建议最多 一个 种未命名的参数,并且只有在很明显必须是什么的情况下,例如文件名。
虽然所有这些都是可能的,但像 Getopt
这样的模块恰好存在,因此我们不必这样做。
† 看起来不像选项的输入操作是使用 '<>'
的“名称”设置的
Getoptions( 'opt=s' => $var, ..., '<>' => \&arg_cb );
sub arg_cb { say "Doesn't look like an option: $_[0]" }
只有在看到非选项参数 .
时才会调用子 arg_cb
我正在使用 Getopt::Long 将选项传递给我的 Perl 脚本。
但我想做这样的事情:
perl myScript mandatoryArgument1 -optionalArgument1=someValue
我希望脚本在缺少 mandatoryArgument1 时抛出错误。如何做到这一点?
我对 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
,否则我中止执行打印程序的帮助。
我不会将 named 形式的 --param=*value*
输入参数与无命名参数混合使用。
也就是说,您可以在调用 Getopt::Long
之前操作 @ARGV
并将其配置为执行您要求的操作,但是混合两种类型的输入参数 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
您必须将强制参数限制在固定位置(在我的示例中是问题中的第一个,但也可能是最后一个)。
好的 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) {
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: [=10=] ..."; # 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();
};
一旦 Getopt
选取了命名参数,您必须手动处理 @ARGV
。
如果有多个这样的参数,用户必须严格遵守它们在命令行上的预期相对位置,因为程序通常无法分辨什么是什么。所以一般情况下,用户在命令行上混淆顺序的错误是无法捕获的。
这会成为一个障碍,我建议最多 一个 种未命名的参数,并且只有在很明显必须是什么的情况下,例如文件名。
虽然所有这些都是可能的,但像 Getopt
这样的模块恰好存在,因此我们不必这样做。
† 看起来不像选项的输入操作是使用 '<>'
Getoptions( 'opt=s' => $var, ..., '<>' => \&arg_cb );
sub arg_cb { say "Doesn't look like an option: $_[0]" }
只有在看到非选项参数 .
时才会调用子arg_cb