Использование динамически сгенерированного имени переменной в строгом режиме Perl

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

Вот что я хочу сделать:

# Fields:
$q1 = "ex. data 1";
$q2 = "ex. data 2";
$q3 = "ex. data 3";
$q4 = "ex. data 4";
$q5 = "ex. data 5";

# retrieve the desired field name.  q1, q2, q3, q4, or q5.
$field_name = fetch_the_desired_field_name();

# fetch the contents of the named field.  ex. data 1, ex. data 2, etc.
$contents_of_desired_field = $$field_name;

print $contents_of_desired_field;

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


person user2543941    schedule 02.07.2013    source источник
comment
Я пробовал это несколько недель назад, но просто не смог заставить его работать в строгом режиме. Вы пробовали этот вопрос на PerlMonks?   -  person Rick Sarvas    schedule 03.07.2013


Ответы (3)


Для этого с хешем:

Магазин:

$myHash{q3} = "ex. data 3";

Забрать:

$result = $myHash{q3};

Это дает множество преимуществ, таких как:

  • Удовлетворяет "строгое использование";

  • Вы можете перебрать все имена полей с помощью keys %myHash

  • Поскольку имена полей представляют собой список в соответствии с последним пунктом, вы можете при необходимости выполнять с ними любые другие операции со списком (map, grep) и т. Д.

    • Например, чтобы получить только те значения, в которых имя поля имеет форму «q [1-5]», вы можете:

      @subset = @myHash{ grep m/q[1-5]/ keys %myHash }; # Use a slice @{} operator.
      
    • Большинство API-интерфейсов баз данных (например, DBI) имеют вызовы, которые автоматически возвращают этот точный формат хэша (или, скорее, вместо этого хеш-ссылку) при запросе строки из таблицы.

      $hash_ref = $sth->fetchrow_hashref;
      
person DVK    schedule 02.07.2013

Вы не хотите динамически генерировать имена переменных! Вместо этого используйте хеш или массив:

my @q = ("ex. data 1", ..., "ex. data 5");

my $contents  = $q[ $some_index ];

print $contents;

Где $some_index установлен на желаемый индекс, что устраняет необходимость в динамических именах.

person amon    schedule 02.07.2013

strict явно не позволяет использовать так называемые «символические ссылки». Вы можете обойти это, спросив Perl о разрешении:

use strict;
use warnings;
use 5.10.0;

our $x = '5';
my $field_name = 'x';

my $contents;
{ # no strict is lexially scoped
    no strict 'refs';
    $contents = ${$field_name};
}

say $contents;

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

# Fields:
my %data = (
    q1 => "ex. data 1",
    q2 => "ex. data 2",
    q3 => "ex. data 3",
    q4 => "ex. data 4",
    q5 => "ex. data 5",
);

# retrieve the desired field name.  q1, q2, q3, q4, or q5.
$field_name = fetch_the_desired_field_name();

# fetch the contents of the named field.  ex. data 1, ex. data 2, etc.
$contents_of_desired_field = $data{$field_name};

print $contents_of_desired_field;

Там. Никакого беспорядка no strict, только одна переменная, содержащая все ваши данные.

person darch    schedule 02.07.2013
comment
Кажется, это правильный путь. Спасибо за ответ! - person user2543941; 03.07.2013
comment
Это работает, но помните, что есть причина, по которой это не допускается: это почти всегда очень плохая идея. - person Flimzy; 03.07.2013
comment
@ user2543941 Мы не можем достаточно подчеркнуть это: вы пожалеете об использовании символических ссылок. - person darch; 03.07.2013