Я столкнулся с интересной проблемой со следующим фрагментом кода в perl 5.22.1 и perl 5.30.0
use strict;
use warnings;
use feature 'say';
#use Data::Dumper;
my %hash;
my %seen;
my @header = split ',', <DATA>;
chomp @header;
while(<DATA>) {
next if /^\s*$/;
chomp;
my %data;
@data{@header} = split ',';
push @{$hash{person}}, \%data;
push @{$hash{Position}{$data{Position}}}, "$data{First} $data{Last}";
if( ! $seen{$data{Position}} ) {
$seen{$data{Position}} = 1;
push @{$hash{Role}}, $data{Position};
}
}
#say Dumper($hash{Position});
my $count = 0;
for my $person ( @{$hash{person}} ) {
say "Person: $count";
say "Role: $person->{Position}";
}
say "---- Groups ----\n";
while( my($p,$m) = each %{$hash{Position}} ) {
say "-> $p";
my $members = join(',',@{$m});
say "-> Members: $members\n";
}
say "---- Roles ----";
say '-> ' . join(', ',@{$hash{Role}});
__DATA__
First,Last,Position
John,Doe,Developer
Mary,Fox,Manager
Anna,Gulaby,Developer
Если код работает как есть - все работает нормально
Теперь достаточно добавить $count++
приращение, как показано ниже, и код выдаст ошибки
my $count = 0;
for my $person ( @{$hash{person}} ) {
$count++;
say "Person: $count";
say "Role: $person->{Position}";
}
Ошибки:
Error(s), warning(s):
Use of uninitialized value $data{"Position"} in hash element at source_file.pl line 22, <DATA> line 2.
Use of uninitialized value $data{"Position"} in hash element at source_file.pl line 23, <DATA> line 2.
Use of uninitialized value $data{"Position"} in hash element at source_file.pl line 24, <DATA> line 2.
Use of uninitialized value $data{"Position"} in hash element at source_file.pl line 22, <DATA> line 3.
Use of uninitialized value $data{"Position"} in hash element at source_file.pl line 23, <DATA> line 3.
Use of uninitialized value $data{"Position"} in hash element at source_file.pl line 22, <DATA> line 4.
Use of uninitialized value $data{"Position"} in hash element at source_file.pl line 23, <DATA> line 4.
Use of uninitialized value in concatenation (.) or string at source_file.pl line 35, <DATA> line 4.
Use of uninitialized value in concatenation (.) or string at source_file.pl line 35, <DATA> line 4.
Use of uninitialized value in concatenation (.) or string at source_file.pl line 35, <DATA> line 4.
Use of uninitialized value in join or string at source_file.pl line 48, <DATA> line 4.
Эта проблема не проявляется в perl 5.30.0 (Windows 10, Strawberry Perl) или Perl v5.24.2 .
Примечание: проблема проявляется не только с $count++
, но и с любым другим доступом к содержимому га sh рядом с say "Person: $count";
- post # 60653651
Я хотел бы услышать комментарии к этой ситуации, в чем причина?
ПРИЧИНА: входные данные имеют eol в форме DOS \r\n
и при обработке данных в Linux chomp
удаляется только \n
, оставляя \r
как часть имени поля (используется как ключ ha sh). Спасибо Шон за указание на источник проблемы.
РЕШЕНИЕ: универсальное исправление реализовано в виде подпрограммы snip_eol($arg)
use strict;
use warnings;
use feature 'say';
my $debug = 0;
say "
Perl: $^V
OS: $^O
-------------------
" if $debug;
my %hash;
my %seen;
my @header = split ',', <DATA>;
$header[2] = snip_eol($header[2]); # problem fix
while(<DATA>) {
next if /^\s*$/;
my $line = snip_eol($_); # problem fix
my %data;
@data{@header} = split ',',$line;
push @{$hash{person}}, \%data;
push @{$hash{Position}{$data{Position}}}, "$data{First} $data{Last}";
if( ! $seen{$data{Position}} ) {
$seen{$data{Position}} = 1;
push @{$hash{Role}}, $data{Position};
}
}
#say Dumper($hash{Position});
my $count = 0;
for my $person ( @{$hash{person}} ) {
$count++;
say "-> Name: $person->{First} $person->{Last}";
say "-> Role: $person->{Position}\n";
}
say "---- Groups ----\n";
while( my($p,$m) = each %{$hash{Position}} ) {
say "-> $p";
my $members = join(',',@{$m});
say "-> Members: $members\n";
}
say "---- Roles ----";
say '-> ' . join(', ',@{$hash{Role}});
sub snip_eol {
my $data = shift; # problem fix
#map{ say "$_ => " . ord } split '', $data if $debug;
$data =~ s/\r// if $^O eq 'linux';
chomp $data;
#map{ say "$_ => " . ord } split '', $data if $debug;
return $data;
}
__DATA__
First,Last,Position
John,Doe,Developer
Mary,Fox,Manager
Anna,Gulaby,Developer