У хорошего 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
вызывается только в том случае, если просматривается неопциональный аргумент.
person
zdim
schedule
26.05.2016