Боюсь, это все довольно запутанно.Я думаю, что основная проблема заключается в использовании глобальных переменных.Подпрограмма должна всегда использовать переменные, которые либо передаются в нее в качестве параметров, либо определяются внутри нее.Кроме того, хранение данных о животном в трех разных хэшах - это путь к катастрофе.Как вы видели, вы не можете гарантировать, что различные хеши остаются в шаге.
Давайте начнем с написания подпрограммы, которая берет один из ваших «абзацев» данных об одном животном и превращает его вхэш.
sub parse_animal {
my ($input) = @_;
my %animal;
for (split /\n/, $input) {
next unless /\S/;
if (/Id:\s+(\S+)/) {
$animal{id} = $1;
next;
}
if (/Loc:\s+(\S+)/) {
$animal{loc} = $1;
next;
}
if (/Similarity:\s+(\S+)/) {
$animal{simil} = $1;
next;
}
warn "Unknown data line: $_";
}
return \%animal;
}
Это очень похоже на ваш код, за исключением того, что он использует только данные, передаваемые в качестве параметров, и создает и возвращает хэш информации.
Мы можем проверить это, вставивзапрограммируйте это так:
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
use Data::Dumper;
my $animal1 = 'animals.dat';
open(my $fh, "<", $animal1) || die "Could not open file $animal1: $!\n";
local $/ = '';
while (<$fh>) {
my $animal = parse_animal($_);
say Dumper $animal;
}
sub parse_animal {
...
}
Мы используем Data :: Dumper здесь, чтобы увидеть, что вы получите от подпрограммы.Я получаю это:
$VAR1 = {
'loc' => 'Area1',
'id' => 'Animal1',
'simil' => '15/20'
};
$VAR1 = {
'simil' => '19/20',
'id' => 'Animal2',
'loc' => 'Area2'
};
$VAR1 = {
'simil' => '13/20',
'id' => 'Animal3',
'loc' => 'Area3'
};
Итак, мы можем видеть, что а) мы правильно анализируем данные и б) данные для каждого животного хранятся вместе в одном хеше.
что на самом деле с данными, которые мы получаем обратно?Ну, есть (по крайней мере!) Пара вариантов.И то, что выбрать, зависит от того, что вы хотите, чтобы ваша программа делала.
Если вы хотите обрабатывать информацию о животных в том порядке, в котором они появляются во входном файле, то имеет смысл хранить их в массиве..
my @animals;
while (<$fh>) {
push @animals, parse_animal($_);
}
for (@animals) {
say "The $_->{id} is found in $_->{loc} and is $_->{simil} similar";
}
Другой вариант может заключаться в том, чтобы хранить их в хэше (возможно, по идентификатору):
my %animals;
while (<$fh>) {
my $animal = parse_animal($_);
$animals{$animal->{id}} = $animal;
}
say Dumper \%animals;
Но, надеюсь, это дало вам достаточно информации, чтобы получить васотключился.