Может ли Getopt::Long вмещать имена опций переменных?

Я пишу скрипт, который может делать что-то вроде:

имя-скрипта --resource1=xxx --resource2=xxx

Но это может доходить до 50+. Есть ли способ заставить GetOpt принимать имена динамических опций?


person gdanko    schedule 13.06.2011    source источник
comment
Должны ли опции работать таким образом? Такие вещи, как --resources=xxx,xxx, которые работают с одним параметром, исключены?   -  person    schedule 13.06.2011
comment
Нет, потому что это довольно сложно. Это расширенный check_http для nagios. --resource1='/foo' --resource1_hostheader='bar' --resource1_rc='200' и так далее. Итак, в настоящее время я помещаю их в хэш для каждого; %resource_hash, %resource_hostheader_hash и т. д.   -  person gdanko    schedule 13.06.2011
comment
тогда, возможно, вы захотите сохранить эту информацию в одной опции, а не в нескольких, а затем использовать повторяющуюся опцию, например: --resource=/foo:bar:200 --resource=/foo2:bar2:300 и т. д..   -  person P Shved    schedule 13.06.2011
comment
Павел, это ВОЗМОЖНО, потому что есть около 20 вариантов для каждого ресурса, и если пользователь не запомнил порядок, все может стать хаотичным.   -  person gdanko    schedule 13.06.2011


Ответы (4)


Как насчет автоматического создания списка параметров для Getopt::Long, как в примере ниже? Поскольку список параметров, вероятно, будет довольно длинным, использование Getopt::ArgvFile позволит вы должны предоставить файл конфигурации с параметрами вместо того, чтобы указывать их в командной строке.

use Getopt::Long;
use Getopt::ArgvFile;
use Data::Dump;

my @n = (1 .. 10);    # how many resources allowed
my %opts = (
    port                  => ':i',
    http_version          => ':s',
    invert_string         => ':s',
    ssl                   => '',
    expect                => ':s',
    string                => ':s',
    post_data             => ':s',
    max_age               => ':i',
    content_type          => ':s',
    regex                 => ':s',
    eregi                 => ':s',
    invert_regex          => '',
    authorization         => ':s',
    useragent             => ':s',
    pagesize              => ':s',
    expected_content_type => ':s',
    verify_xml            => '',
    rc                    => ':i',
    hostheader            => ':s',
    cookie                => ':s',
    encoding              => ':s',
    max_redirects         => ':i',
    onredirect_follow     => ':i',
    yca_cert              => ':s',
);

my %args = ();
GetOptions(\%args,
    map {
        my $i = $_;
        ( "resource$i:s", map { "resource${i}_$_$opts{$_}" } keys %opts )
    } @n
) or die;

dd \%args;
person bvr    schedule 13.06.2011
comment
Я не думаю, что стал бы создавать @n. Просто создайте переменную $n, и тогда вы сможете генерировать список 1 .. $n в любое время, когда вам это нужно, что, вероятно, будет происходить не очень часто. - person cjm; 14.06.2011
comment
@cjm - хороший момент, в этом случае это было бы еще более очевидно. - person bvr; 14.06.2011

Будет ли это работать с одним и тем же именем параметра повторяется?

Например: script-name --resource=xxx --resource=xxx

person Kevin ORourke    schedule 13.06.2011
comment
Я так не думаю. Посмотреть количество вариантов, доступных для каждого ресурса, можно здесь: pastebin.gdanko.net/441 - person gdanko; 13.06.2011

Да, поскольку я только что понял, как это сделать сам, поскольку я хотел принять аргумент -#, а Getopt::Long не принимает регулярное выражение для имени параметра. Итак, вот что я сделал:

use Getopt::Long qw(:config pass_through);

my $ret=GetOptions(
    \%gops,
    'lines|l',  # lines/records to display
    ... cut ...
    '<>' => \&filearg,          # Handle file names also attach current options
);

Затем я определил функцию filearg():

sub filearg {
    my $arg=shift;

    # First see if it is a number as in -20 as shortcut for -l 20
        if ($arg =~ /^--?(\d)+$/) {
        $gops{'lines'}=$1;
    } elsif (-f "$arg" && -r "$arg") {
        my %ops=%gops;
        $fops{$arg}=\%ops;
        push(@files, $arg);
    } else {
        push(@badargs, $arg);
    }
    return(undef);
}

Итак, что необходимо, так это опция pass_through, проверка того, что вы хотите, и настройка этих вещей, когда они видны. Выше у меня были неопределенные параметры, переданные моей функции. Я использую это для проверки файлов и специальной опции -#, где # — целое число. Если он не совпадает, я добавляю в массив badargs, так как это не приведет к сбою GetOptions, поэтому я должен проверить этот массив после возврата из GetOptions, чтобы увидеть, были ли замечены ошибки. Вы также можете завершить его при ошибке опции, завершив функцию обратного вызова с помощью die("!FINISH");, что заставит GetOptions завершить скрипт.

Я использую его для возможности иметь что-то вроде -20 FILE1 -30 FILE2, поэтому параметры могут быть переопределены для последующих файлов. Я вижу, что вы можете сделать что-то подобное с проверкой первой части имени параметра, а затем значения. Итак, если все ваши параметры начинаются с --resource, найдите что-то подобное в своей функции: /^--?(resource\w+)=(.*)$/, а затем добавьте в массив параметров.

Во всяком случае, надеюсь, что это поможет.

person Dave    schedule 25.07.2011

Другой метод, который можно попробовать, - просто использовать какой-то файл конфигурации. Кажется, что это может быть самый простой способ как для записи, так и для анализа, учитывая, что вы планируете иметь большой объем информации.

person Matthew    schedule 13.06.2011