Data :: Dumper包装第二个单词的输出

时间:2016-09-30 20:46:02

标签: perl data-dumper

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

有人知道翻车机打印的原因吗?我的第二列数据的前两个字母上的字符?

3 个答案:

答案 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)

嗯......这对我来说似乎不对,即使你正在使用Perl6:

%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 =~ /^#/;可以避免大量缩进。