3

我在使用 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

有谁知道为什么 Dumper 打印 '; 我的第二列数据的前两个字母上的字符?

4

3 回答 3

1

代码中有一个不清楚的地方:是*product_names散列还是散列引用?

  • 如果是散列,你应该使用%product_names{key}语法,not %product_names->{key},并且需要传递对 Data::Dumper的引用,所以Dumper(\%product_names).

  • 如果它是一个 hashref,那么它应该用正确的符号标记,所以$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

    # ...
}

我已更改为词法文件句柄,这是具有许多优点的推荐做法。我还添加了一个检查open,它应该始终存在。

于 2016-09-30T21:04:12.683 回答
1

嗯...这对我来说似乎是错误的,即使您使用的是 Perl6:

%product_names->{$words[0]} = $words[1];

我不太了解 Perl6,但在 Perl5 中,考虑到 %product_names 存在并被声明,参考应该如下所示:

$product_names{...} = ... ;

如果你能公开完整的代码,我可以帮助解决这个问题。

于 2016-09-30T21:32:57.123 回答
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 =~ /^#/;会避免大量缩进。
于 2016-09-30T21:15:14.710 回答