Добавляйте параметры Getopt::Long в хэш, даже если используется спецификатор повтора.

Perl Getopt::Long позволяет разработчику добавлять в скрипт свои собственные параметры. Также можно разрешить несколько значений параметра с помощью использования спецификатор повторения, как это видно в регулярных выражениях. Например:

GetOptions('coordinates=f{2}' => \@coor, 'rgbcolor=i{3}' => \@color);

Кроме того, значения параметров можно хранить в хеше. вот так:

my %h = ();
GetOptions(\%h, 'length=i');    # will store in $h{length}

Что я пытаюсь сделать, так это объединить эти два метода, чтобы получить хэш моих опций, даже если они имеют несколько значений.

Например, я хочу разрешить три параметра: день рождения (три целых числа), родители (одна или две строки), имя (ровно одна строка). Допустим также, что я хочу поместить эти значения в хэш. Я пробовал следующее:

use strict;
use warnings;

use Getopt::Long;
use Data::Dumper;

my %h = ();
GetOptions(\%h, 'bday=i{3}', 'parents=s{1,2}', 'name=s{1}');

print Dumper(\%h);

И проверил это, но вывод был следующим:

perl optstest.pl --bday 22 3 1986 --parents john mary --name ellen
$VAR1 = {
    'name' => 'ellen',
    'parents' => 'mary',
    'bday' => 1986
};

Только последнее значение каждой опции фактически используется в хеше. Что бы я хотел, однако, это:

$VAR1 = {
    'name' => 'ellen',
    'parents' => ['mary', 'john'],
    'bday' => [22, 3, 1986]
};

Если бы «эллен» была бы в массиве или если бы все было внутри хэша, это тоже было бы хорошо.

Разве нельзя объединить эти две функции Getopt::Long, т.е. поместить параметры в хэш и использовать спецификаторы повторения?


person Bram Vanroy    schedule 18.04.2017    source источник


Ответы (3)


use Getopt::Long;
# enable for debugging purposes
# Getopt::Long::Configure("debug");
use Data::Dumper;

my %h = ();
GetOptions(\%h, 'bday=i{3}', 'parents=s@{1,2}', 'name=s@{1}');

print Dumper(\%h);

Это то, что вы хотите?

$VAR1 = { 
          'bday' => 1986,
          'name' => [ 
                      'ellen'
                    ],
          'parents' => [ 
                         'john',
                         'mary'
                       ]
        };
person palik    schedule 18.04.2017
comment
Я хотел bday как массив, но на самом деле. Мне нужна нотация @{}. Спасибо! - person Bram Vanroy; 18.04.2017

Если вам нужен массив, вам нужно указать ссылку на массив.

local @ARGV = qw( --x y z );
my %h = ( x => [] );
GetOptions(\%h, 'x=s{2}');
print(Dumper(\%h));

Или вам нужно указать, что вы хотите массив.

local @ARGV = qw( --x y z );
GetOptions(\my %h, 'x=s@{2}');
print(Dumper(\%h));

Выход:

$VAR1 = {
          'x' => [
                   'y',
                   'z'
                 ]
        };
person ikegami    schedule 18.04.2017
comment
Спасибо за ответ! Мне не очень нравится первый вариант. Прежде всего потому, что он будет генерировать пустые массивы, даже если параметр не указан в CLI. Это просто непрактично: простая проверка существования опции с помощью exists $h{'option'} всегда будет возвращать true, даже если она не установлена. Я не могу представить, что разработчики GetOpt предполагали такое использование. Однако второе предложение работает нормально, поэтому я воспользуюсь им. Спасибо. - person Bram Vanroy; 18.04.2017

Параметры с несколькими значениями раздел документации, на который вы ссылаетесь, также говорит об этом

Предупреждение: нижеследующее является экспериментальной функцией.

Это говорит ранее на

GetOptions (\%h, 'colors=s@'); # отправит в @{$h{colors}}

поэтому я предполагаю, что автор хотел, чтобы он работал так же с спецификаторами повторения, и что вы нашли ошибку

Я предлагаю вам сообщить об этом портировщикам Perl 5, используя утилиту perlbug, которая является частью установки Perl.

person Borodin    schedule 18.04.2017
comment
Учитывая другие ответы здесь, вы все еще думаете, что это ошибка? Предлагаемый ответ с использованием @{1,2} отлично работает, но, возможно, вы думаете, что он также должен работать без объявления типа? - person Bram Vanroy; 18.04.2017
comment
@BramVanroy: Абсолютно. Если синтаксис, который вы использовали, неверен, он не должен приниматься модулем. Если он правильный, то он должен работать. Ни при каких обстоятельствах он не должен молча терять все, кроме одного значения параметра, который был специально определен как многозначный. Я сам подниму этот вопрос, если хотите? - person Borodin; 18.04.2017
comment
@BramVanroy: я думаю, я говорю, что parents=s{1,2} всегда должно вести себя как parents=s@{1,2}, потому что рассматривать такое значение как простой скаляр - это нонсенс. - person Borodin; 18.04.2017