Я перебираю ваш код очень быстро:
#!/usr/bin/perl -w
-w
не рекомендуется.Вместо этого вы должны use warnings;
(что вы уже делаете, поэтому просто удалите -w
).
use strict;
use warnings;
Очень хорошо.
use Data::Dumper;
my $input= $ARGV[0];
ОК.
my %hash;
Не объявляйте переменные, пока они вам не понадобятся.Объявите их в наименьшей возможной области видимости, обычно непосредственно перед их первым использованием.
open my $data , '<', $input or die " cannot open file : $_\n";
В начале вашего сообщения об ошибке у вас есть ложное пространство, и $_
на этом этапе не установлен.Вместо этого вы должны включить $input
(имя файла, который не удалось открыть) и $!
(причина ошибки).
my @names = split ' ', $data;
my @values = split ' ', $data;
Ну, это не имеет смысла.$data
это дескриптор файла, а не строка.Даже если бы это была строка, этот код назначил бы один и тот же список для @names
и @values
.
@hash{@names} = @values;
print Dumper \%hash;
Моя версия (не проверено):
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
@ARGV == 1
or die "Usage: $0 FILE\n";
my $file = $ARGV[0];
my %hash;
{
open my $fh, '<', $file or die "$0: can't open $file: $!\n";
local $/ = '';
while (my $paragraph = readline $fh) {
my @words = split ' ', $paragraph;
my $key = shift @words;
$hash{$key} = \@words;
}
}
print Dumper \%hash;
Идея состоит в том, чтобы установить $/
( разделитель входных записей ) на ""
на время цикла ввода, что заставляет readline
возвращать целые абзацы, а не строки.
Первое (через пробел) слово каждого абзаца считается ключевым;остальные слова являются значениями.