Как я могу обнаружить ошибки комбинированного аргумента, используя Getopt :: Euclid? - PullRequest
1 голос
/ 04 июня 2009

Я вынужден (по технической политике) использовать Getopt :: Euclid для анализа аргументы к моей программе Perl. У меня есть три аргумента: фу, бар и бла.

Вполне допустимо не иметь ничего из этого и использовать вместо этого другие аргументы.

Если присутствует foo, то должен присутствовать ровно один из баров или бла, и если присутствует либо bar, либо blah, то должен присутствовать foo.

После прочтения документации CPAN я не вижу способа получить Euclid обнаружить и обеспечить соблюдение этих ограничений. Если Евклид МОЖЕТ применять эти ограничения, я хотел бы понять, как.

В противном случае я сам определю условия, но хотел бы уговорить Евклид в генерацию вывода --help, если условия нарушены, но не могу понять, как это сделать изнутри программы. Идеи?

Ответы [ 4 ]

1 голос
/ 05 июня 2009

Похоже, что вы можете использовать раздел OPTIONS для своих опций, и он не будет жаловаться, если их нет, но я не вижу никакой логики для разрешения зависимых опций, поэтому вам придется написать эту логику сам. Я также не вижу функций, которые будут распечатывать использование, но вы всегда можете сказать

system $^X, $0, "--help";

, который запустит скрипт ($0) с тем же интерпретатором ($^X), с которым он был вызван, и передаст ему аргумент --help. Это некрасиво, но должно работать.

#!/usr/bin/perl

use strict;
use warnings;

use Getopt::Euclid;

sub usage {
    my $message = shift;
    print "$message\n\n";
    system $^X, $0, "--help";
}

if (keys %ARGV) {
    unless (exists $ARGV{'--foo'}) {
        usage "--foo must be present if --bar or --blah is present";
        exit -1;
    }

    if ($ARGV{'--bar'} and $ARGV{'--blah'}) {
        usage "only one of --bar or --blah may be present";
        exit -1;
    }
}

unless ($ARGV{'--foo'}) {
    print "Doing nothing\n";
    exit 0;
}

print "fooing bar\n"  if $ARGV{'--bar'};
print "fooing blah\n" if $ARGV{'--blah'};


__END__

=head1 NAME 

foo.pl - foo the bar 

=head1 VERSION

1.0

=head1 usage 

    foo.pl [options]

=head1 OPTIONS

=over

=item --foo

do the foo (requires --bar or --blah)

=item --bar

what to do the foo to (requires --foo)

=item --blah

what to do the foo to (requires --foo)

=item --help

=back

=head1 AUTHOR

Chas. J. Owens IV

=head1 BUGS

Hopefully none

=head1 COPYRIGHT

Copyright (c) 2009, Chas. J. Owens IV. All Rights Reserved.
This module is free software. It may be used, redistributed
and/or modified under the terms of the Perl Artistic License
(see http://www.perl.com/perl/misc/Artistic.html)
0 голосов
/ 09 февраля 2013

Вы можете использовать ключевое слово 'exclude' начиная с версии 0.2.4 Getopt :: Euclid (выпущено в июне 2011 года) для указания взаимоисключающих аргументов.

0 голосов
/ 05 декабря 2009

Как насчет функций, описанных в разделе «Ограничения местозаполнения» руководства Getopt :: Euclid? В частности, эта форма:

PLACEHOLDER.type: TYPE [, EXPRESSION_INVOLVING(PLACEHOLDER)]

EXPRESSION_INVOLVING может быть любым произвольным выражением perl, я считаю. Это даже не должно включать сам вариант. Таким образом, выражения ограничений для bar и blah могут каждое проверить, что другое не существует и что foo существует.

Единственная проблема в том, что это, вероятно, накладывает зависимость порядка от ваших аргументов. Это было бы законно: --foo --bar; но это не так: --bar --foo, потому что, когда аргумент --bar читается, Евклид еще не знает о --foo, поэтому хрипит. Поэтому, если вы идете по этому пути, обязательно укажите сообщение об ошибке для этого эффекта --bar.

0 голосов
/ 05 июня 2009

Мне кажется (никогда не использовал G :: E и не проверял), как будто вы хотите притвориться, что это всего лишь один вариант:

=head1 OPTIONS

=over

=item --foo <foo> --bar <bar> | --foo <foo> --baz <baz>

затем используйте $ARGV{'--foo'}{'foo'} и $ARGV{'--foo'}{'bar'} или $ARGV{'--foo'}{'baz'}.

Я предполагаю, что они все принимают аргументы; Вы не ясно дали понять.

Обновление: похоже, работает, хотя выдает вводящие в заблуждение сообщения об ошибках, если вы опускаете bar или baz или указываете оба. Если ни один из переключателей не принимает аргументы, вы можете сделать:

=item --foo --bar | --foo --baz

=for Euclid
    false: --foo --baz

и $ARGV{'--foo'} будут иметь значение true для бара, false для baz и не существуют, если ни того, ни другого.

В долгосрочной перспективе вам может быть лучше отправить Getopt :: Euclid автору патч, который допускает что-то вроде:

=item --foo

=for Euclid
    requires: --bar | --baz

=item --bar

=for Euclid
    requires: --foo

=item --baz

=for Euclid
    requires: --foo

, поэтому он может выдавать значимые сообщения об ошибках, если указаны несовместимые параметры.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...