在使用Data :: Dumper尝试检查我将大量数据导入哈希时,我遇到了一个相当奇怪的问题。
我的数据在另一个文件中看起来像这样。
##Product ID => Market for product
ABC => Euro
XYZ => USA
PQR => India
然后在我的脚本中,我试图将我的数据列表读入一个像这样的哈希:
open(CONFIG_DAT_H, "<", $config_data);
while(my $line = <CONFIG_DAT_H>) {
if($line !~ /^\#/) {
chomp($line);
my @words = split(/\s*\=\>\s/, $line);
%product_names->{$words[0]} = $words[1];
}
}
close(CONFIG_DAT_H);
print Dumper (%product_names);
我的解析工作大部分都是我可以在哈希中找到我的所有数据,但是当我使用Data :: Dumper打印它时,它不能正确打印它。这是我的输出。
$VAR1 = 'ABC';
';AR2 = 'Euro
$VAR3 = 'XYZ';
';AR4 = 'USA
$VAR5 = 'PQR';
';AR6 = 'India
有人知道翻车机打印的原因吗?我的第二列数据的前两个字母上的字符?
答案 0 :(得分:1)
代码中有一个不清楚的东西:是*product_names
散列还是hashref?
如果是哈希,则应使用%product_names{key}
语法,而不是%product_names->{key}
,并且需要将引用传递给Data::Dumper,因此Dumper(\%product_names)
。< / p>
如果是hashref,则应使用正确的sigil标记,因此$product_names->{key}
和Dumper($product_names}
。
如mob所述,如果您的输入中包含\n
之外的其他内容,则需要更明确地清除它,例如每条评论s/\s*$//
。请参阅ikegami的答案。
我还想补充一点,通过放弃if
分支可以简化循环
open my $config_dat_h, "<", $config_data or die "Can't open $config_data: $!";
while (my $line = <$config_dat_h>)
{
next if $line =~ /^\#/; # or /^\s*\#/ to account for possible spaces
# ...
}
我已经改为lexical filehandle,推荐的做法有很多优点。我还添加了open
的支票,该支票应该始终存在。
答案 1 :(得分:1)
%product_names->{$words[0]} = $words[1];
我不太了解Perl6,但在Perl5中,考虑到%product_names存在并被声明,引用应该如下:
$product_names{...} = ... ;
如果您可以公开完整的代码,我可以帮助解决这个问题。
答案 2 :(得分:0)
该文件使用CR LF作为行结尾。通过在代码中添加以下内容可以明显看出这一点:
local $Data::Dumper::Useqq = 1;
您可以将文件转换为使用unix行结尾(看到你在unix系统上)。这可以使用dos2unix
实用程序来实现。
dos2unix config.dat
或者,替换
chomp($line);
更灵活
$line =~ s/\s+\z//;
%product_names->{$words[0]}
毫无意义。它碰巧在旧版本的Perl中做你想要的,但它在新版本中合理地抛出错误。 $product_names{$words[0]}
是访问哈希元素值的正确语法。print Dumper(\%product_names);
代替print Dumper(%product_names);
。local $Data::Dumper::Sortkeys = 1;
有用。 Data :: Dumper有如此糟糕的默认值:(split(/\s*=>\s*/, $line, 2)
代替split(/\s*=>\s*/, $line)
会允许该值包含=>
。open(my $CONFIG_DAT_H, ...)
代替open(CONFIG_DAT_H, ...)
,并将CONFIG_DAT_H
的其他实例替换为$CONFIG_DAT_H
。next if $line =~ /^#/;
可以避免大量缩进。