В Perl, как получить доступ к переменной, определенной в другом пакете - PullRequest
0 голосов
/ 08 ноября 2019

У меня есть сгенерированный Perl-скрипт, который я не могу контролировать. Он определяет пакет и хеш. Мне нужно получить доступ к хешу из другого сценария perl, над которым у меня есть полный контроль.

сгенерированный сценарий perl:

package Animals;

my %pets = (
  'cat' => {
     'legs' => 4,
     'name' => 'Garfield',
     'speak' => 'Meowrrr!'
  },
  'bird' => {
     'legs' => 2,
     'name' => 'Tweety',
     'speak' => 'Pi pi pi!'
  },
  'dog' => {
     'legs' => 4,
     'name' => 'Pluto',
     'speak' => 'Wooof wooof!'
  }
)

Другой сценарий perl, которым я управляю:

sub main {
  #some other code
  require Animals;
  #some other code
  #print for instance the what the bird's saying
  print $Animals::pets->{'bird'}->{'speak'};
}

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

Ответы [ 2 ]

3 голосов
/ 09 ноября 2019

Поскольку присвоение хешу - последнее, что есть в файле, вы можете использовать

my %pets = do('Animals.pm');
$pets{bird}{speak}

Но сама концепция «у меня есть сгенерированный файл в непригодном для использования формате» не имеет смысла. При изменении сгенерированного вывода убедитесь, что вы используете что-то правильное, например JSON или YAML.

2 голосов
/ 08 ноября 2019

Смысл лексической переменной (то есть той, которая объявлена ​​с my) заключается в том, что ее можно увидеть только внутри ее собственной лексической области видимости. Его лексическая область видимости является самым внутренним блоком кода, который содержит объявление переменной или (при отсутствии такого блока) файл, содержащий объявление переменной.

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

Если у вас есть переменная, которую нужно видеть в лексических областях, то вам нужно сделать ее переменной пакета. То есть вы должны объявить его с our вместо my.

. В вашем случае самое маленькое изменение, которое вы можете внести в сгенерированный модуль, это изменить my на our. Было бы также полезно, если бы вы могли добавить переменную в дополнительный список экспорта модулей.

our @EXPORT_OK = qw[%pets];
our %pets = ( ... );

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

Если вы просто измените my на our, тогда ваш код будет работать так, как он написан в данный момент. Если вы внесете дополнительное изменение @EXPORT_OK, вы можете упростить свой код до:

use Animals qw[%pets];

print $pets->{'bird'}->{'speak'};

, так как %pets будет импортировано в таблицу символов вашего пакета.

...