Perl: возможно ли предотвратить остановку распознавания опций после двойной черты (-) при использовании GetOpt? - PullRequest
1 голос
/ 15 февраля 2011

Я хочу записать в Perl-скриптах, которые получают и вариант со списками значений, который заканчивается двойной чертой (-).пример:

% perl_script -letters a b c -- -words he she we --

в результате выполнения этой командной строки будут созданы два массива: letters = [abc];words = [he she we];

Использование GetOption не поддерживает это, bc после использования двойной черты, распознавание опций прекращается.

Ответы [ 3 ]

5 голосов
/ 15 февраля 2011

У вас есть какая-то конкретная причина использовать такой запутанный разделитель?-- имеет известное значение для большинства пользователей сценариев, и это не так.

Если вам нужно прочитать опции со списками, Getopt::Long имеет методы для работы с массивами ввода, возможно, что-то подобное может вам помочь;смотрите под «Опции с несколькими значениями» .Этот модуль входит в стандартный дистрибутив, поэтому вам даже не нужно ничего устанавливать.Я использую его для любого сценария, который требует более одного (может быть, двух) входных данных и определенно, если какие-либо входные данные являются необязательными.

См. Также здесь и даже больше здесь .

Вот краткий пример: если у вас есть возможность изменить синтаксис ввода, вы получите требуемую функциональность:

#!/usr/bin/env perl
# file: test.pl

use strict;
use warnings;

use Getopt::Long;

my @letters;
my @words;

GetOptions(
  "letters=s{,}" => \@letters,
  "words=s{,}" => \@words
);

print "Letters: " . join(", ", @letters) . "\n";
print "Words: " . join(", ", @words) . "\n";

Дает:

$ ./test.pl --letters a b c --words he she we
Letters: a, b, c
Words: he, she, we

Хотя я никогда не поощрял бы написание собственного парсера, я не мог понять, почему кто-то выбрал форму, которая у вас была, поэтому я буду действовать исходя из того, что вы не контролируете этот формат и вам нужно обойти его,Если это так (в противном случае рассмотрите более стандартный синтаксис и используйте приведенный выше пример), вот простой анализатор, который должен помочь вам начать работу.

NB. Причина, по которой вы НЕ пишете свои собственные, состоит в том, что другие хорошо проверены и имеют сглаженные случаи.Также знаете ли вы, что бы вы сделали с чем-то между -- и -title?Я предположил, что, поскольку новый -title закончил бы предыдущий, вы могли бы иметь что-то среднее между ними и поместить их все по порядку в ключ «default».

#!/usr/bin/env perl
# file: test_as_asked.pl
# @ARGV = qw/default1 -letters a b c -- default2 -words he she we -- default3/;

use strict;
use warnings;

my %opts;
# catch options before a -title (into group called default)
my $current_group = 'default';
foreach my $opt (@ARGV) {
  if ($opt =~ /\-\-/) {
    # catch options between a -- and next -title
    $current_group = 'default';
  } elsif ($opt =~ /\-(.*)/) {
    $current_group = $1;
  } else {
    push @{ $opts{$current_group} }, $opt;
  }
}

foreach my $key (keys %opts) {
  print "$key => " . join(", ", @{ $opts{$key} }) . "\n";
}

Дает:

$ ./test_as_asked.pl default1 -letters a b c -- default2 -words he she we -- default3
letters => a, b, c
default => default1, default2, default3
words => he, she, we
3 голосов
/ 15 февраля 2011

Как насчет

-letters "a b c" -words "he she we" 

?

2 голосов
/ 15 февраля 2011

Вы можете обрабатывать аргументы за несколько проходов, если хотите. Посмотрите на параметр pass_through. Это то, что я делаю в ack , потому что некоторые опции влияют на другие опции, поэтому я должен сначала обработать опции --type, а затем обработать остальные.

...