while() { # чтение одной записи данных
($authors, $title, $year, $nick) = split ':';
write $report; # вывод одной строки отчета
}
close $report or die;
# формат для заголовка страницы
format HEAD =
Классические книги по языку Perl
издательства O'Reilly
Лист @#
$%
---------------+--------------------+----+------------
Авторы | Заглавие |Год | Прозвище
---------------+--------------------+----+------------
.
format REPORT =
^'Бахрейна', date=>'2006.03.12'},
{grandprix=>'Малайзии', date=>'2006.03.19'},
{grandprix=>'Австралии', date=>'2006.04.02'},
{grandprix=>'Сан-Марино', date=>'2006.04.23'},
# и так далее...
];
# напечатать хэш, на который ссылается 4-й элемент массива
print "Гран-при $AoH->[3]->{grandprix} $AoH->[3]->{date}";
# выведет: Гран-при Сан-Марино 2006.04.23
Для того чтобы ассоциировать с каждым ключом хэша список скалярных значений, применяется хэш массивов (Нash of Аrrays, HoA). Приведем пример хэша массивов, где в каждом элементе хэша хранится ссылка на анонимный список ассоциированных значений:
my $HoA = { # годы создания языков программирования
1964 => ['SIMULA', 'BASIC', 'PL/1'],
1970 => ['Forth', 'Pascal', 'Prolog'],
1979 => ['Ada', 'Modula-2'],
1987 => ['Perl', 'Haskell', 'Oberon'],
1991 => ['Python', 'Visual Basic']
};
# напечатать список, ассоциированный с 1987 годом
foreach my $language (sort @{$HoA->{1987}}) {
print "$language ";
} # выведет: Haskell Oberon Perl
Элементы хэша также могут хранить ссылки на другие хэши, образуя хэш хэшей (Нash of Нashes, HoH). Вот пример описания хэша хэшей, где с каждым поисковым ключом ассоциируется анонимный хэш с информацией об объекте:
my $HoH = { # авторы и годы создания языков программирования
'Pascal' => {author=>'Niklaus Wirth', year=>1970},
'Perl' => {year=>1987, author=>'Larry Wall'},
'C' => {author=>'Dennis Ritchie', year=>1972}
};
# в каком году был создан Pascal?
print $HoH->{'Pascal'}->{'year'}; # выведет: 1970
# кто создал язык Си?
print $HoH->{'C'}->{'author'}; # выведет: Dennis Ritchie
Имеющиеся в других языках программирования записи (record) или структуры (struct), в Perl чаще всего представляются в виде хэшей, в которых ключи используются в качестве имен полей и применяются для доступа к значениям полей записи. Для завершающего примера создадим набор записей с информацией о людях. Каждая запись будет анонимным хэшем, а ссылки на записи будут храниться в массиве. В каждой записи дату рождения представим в виде анонимного массива, содержащего год, месяц и день. Вот таким образом:
my $family = [ # массив записей о семье
{name => 'Михаил', birthday => [1958, 11, 12]},
{name => 'Ирина', birthday => [1955, 03, 23]},
{name => 'Маша', birthday => [1980, 07, 27]},
{name => 'Миша', birthday => [1981, 11, 28]},
{name => 'Лев', birthday => [1988, 06, 24]}
];
# напечатаем год рождения Маши:
print "$family->[2]->{birthday}->[0]"; # или проще:
print "$family->[2]{birthday}[0]"; # выведет: 1980
Подобные структуры легко динамически модифицировать при выполнении программы. Например, добавим в каждую запись новое поле - 'address', в котором сохраним ссылку на запись о месте проживания человека. Адрес оформим в виде анонимного хэша из нескольких полей:
# адрес в виде анонимного хэша, в $address - ссылка на него:
$address = {country => 'Россия', index => 641870}; # и т.д.
# добавить поле адреса и поместить туда $address:
foreach my $person (@{$family}) { # пропишем всех
$person->{address} = $address; # по одному адресу
}
# выведем почтовый индекс для Ирины
print "$family->[1]->{address}->{index}\n"; # 641870
На рис. 11.5 приведена ссылочная структура данных, которая получилась в результате выполнения программы. Для доступа по ссылкам ко всем элементам этой структуры используется единственная именованная переменная $family .

>$file" or die;
print $fh $text;
close $fh or die;
}
}
Если переданные аргументы заданы переменными, то массив параметров @_ совмещается с переданными аргументами. Это означает, что изменение элементов массива приведет к изменению значений соответствующих переменных в вызывающей программе. Это можно проиллюстрировать следующим (несколько искусственным) примером:
sub sum2 { # вычислить сумму 2-х чисел
$_[0] = $_[1] + $_[2]; # поместить сумму в 1-й аргумент
return;
}
my $a = 1, $b = 2, $sum = 0;
Читать дальше