[在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
如果代码按原样运行-everything works fine
现在将$count++
增量添加为波纹管和code produces errors就足够了>
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++
显现出来,而且以其他任何方式访问say "Person: $count";
-post# 60653651]之后的哈希值也显示出来。我想听听对此情况的评论,原因是什么?
CAUSE:
输入数据以DOS形式\r\n
具有eol,并且在Linux中处理的数据时,chomp
仅删除\n
,而将\r
作为字段名称的一部分(用作哈希键)。感谢Shawn指出问题的根源。 SOLUTION:
通用fix以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
我遇到了一个有趣的问题,在perl 5.22.1和perl 5.30.0中使用以下代码使用strict;使用警告;使用功能“说”; #use Data :: Dumper;我的%hash;我的%seen;我的@header = ...
我可以通过(在Linux上)首先将源文件转换为Windows样式的\r\n
行尾,然后尝试运行它来复制此行为。因此,我怀疑在测试各种版本时,有时会使用Windows,而在其他时候则使用Linux / Unix,并且没有正确转换文件的行尾。
@chomp
仅删除换行符(Well,$/
的当前值是多余的),因此,在以Windows样式行结尾的字符串上使用时,它将保留回车符。哈希键不是"Position"
,而是"Position\r"
,这不是其余代码使用的键。