Если у меня есть командная строка как:
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
дает
Unknown option: whatever remaining options:
Вам нужно настроить параметр "pass_through" через Getopt :: Long :: Configure ("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'
];
Разве оставшиеся (не проанализированные) значения просто оставлены в @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
как ссылка на массив, поэтому я бы рекомендовал преобразовать!
Я думаю, что ответ здесь, к сожалению, таков: "Нет, не существует способа сделать это именно так, как вы просите, используя Getopt::Long, не разбирая @ARGV самостоятельно". Однако у Ether есть достойный обходной путь. Для большинства людей это особенность, что любой аргумент, похожий на опцию, фиксируется как ошибка. Обычно, вы можете сделать
GetOptions('foo' => \$foo)
or die "Whups, got options we don't recognize!";
, чтобы перехватить/предотвратить передачу странных опций, а затем вы можете поправить пользователя при использовании. В качестве альтернативы, вы можете просто передать и проигнорировать их.