У структуры данных, которую вы показываете, есть одно критическое правило: значение в хэше может быть только скалярным.
Таким образом, чтобы связать многозначную переменную с ключом, используйте ссылку на эту переменную, здесь arrayref. И если значения в этом массиве должны быть более сложными, чем скаляры, вы снова используете ссылку, здесь хеш-значение. & dagger; Таким образом, значением для каждого ключа является arrayref, элементы которого являются hashrefs.
Затем вам нужно узнать, как получить доступ к элементам глубже в структуре. Это тоже не очень сложно: разыменуйте их, и тогда вы сможете работать с ними, как если бы вы использовали массив или хеш.
Все это находится в perldsc , для которого нужно очистить с помощью perlreftut . Полная ссылка perlref .
Когда это используется в вашей проблеме
use warnings;
use strict;
use Data::Dump qw(dd);
my $file = 'data.txt';
open my $fh, '<', $file or die "Can't open $file: $!";
my %result;
while (<$fh>) {
chomp;
my ($key, $name, $role, $age) = split /\s*,\s*/;
push @{$result{$key}}, { name => $name, role => $role, age => $age };
}
dd \%result;
Это печатает правильную структуру данных. Обратите внимание на использование Data :: Dump для просмотра сложной структуры данных. Наиболее часто встречающийся модуль для этого - Data :: Dumper , но есть и другие.
В split выше в качестве разделителя используется регулярное выражение /\s*,\s*/
, поэтому для разделения строки запятой необязательно в окружении пробелов. По умолчанию используется строка для разделения, которая составляет $_
Обратите внимание, что нам не нужно "добавлять ключ" или устанавливать его значение arrayref перед их использованием, как это делается с помощью autovivification . Смотрите, например, эту страницу и эту страницу и эту страницу .
Это сложная функция, которая может укусить при неправильном использовании, поэтому, пожалуйста, прочтите ее.
& dagger; Если массивы или хэши указаны как "элементы" массива, они "сплющиваются" & ndash; их элементы объединяются со всеми другими заданными элементами, и весь совокупный список используется для заполнения массива, и мы получаем один массив со всеми этими элементами. Так
my @ary = 1..3;
my %hash = (a => 10, b => 20);
# Most likely an error:
my @all = (5, @ary, %hash, 100); #--> (5, 1, 2, 3, a, 10, b, 20, 100)
где пары ключ-значение могут появляться в любом порядке, поскольку хеши по сути неупорядочены.
Вместо этого мы берем ссылки на массивы и хэши и пишем
my @all = (5, \@ary, \%hash, 100);
Теперь содержимое @ary
и %hash
сохраняет свою индивидуальность и может быть восстановлено при необходимости.