2016-09-30 66 views
3

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

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

+1

在输入中看起来像回车('\ r')。 'chomp'不会摆脱它们,请尝试像'$ line =〜s/\ s + $ //'更强的东西 – mob

+1

您需要传递一个引用'Dumper(\%product_names)',而不是' %h - > {key}'语法(但是'%h {key}') - 或者 - 如果'* product_names'实际上是一个hashref,那么你需要使用正确的sigil,'$ product_names - > {key }'和'Dumper($ product_names)'。 – zdim

+0

看起来像正则表达式工作。为了确保我理解它,它正在修整任何类型的空白:\ n,\ r,\ t等等,从行尾开始。我不知道chomp()没有杀死其他类型的空白。 –

回答

1

代码中有一个不清楚的东西:是*product_names散列或hashref?

  • 如果它是一个哈希,你应该使用%product_names{key}语法,不%product_names->{key},并需要一个参考传递给Data::Dumper,所以Dumper(\%product_names)

  • 如果它是一个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 

    # ... 
} 

我已经改变了词法文件句柄,具有许多优点,推荐的做法进行简化。我还添加了一张open的支票,该支票应始终存在。

+0

不幸的是,我不认为我知道如果它是一个hashref或hash。两者之间有什么重大区别?我一直对待它的方式是将第一列“产品ID”与第二列“市场”相关联。 我看到在使用dumper打印散列与使用其引用之间存在的巨大差异是从打印每一条数据到将它们打印在适当列表中的格式更改。 –

+0

@JonBot这些是不同的数据结构。如果这是你的所有代码,那么你可以决定是否希望它成为一个hashref或散列 - 然后一致地使用它。 “hashref”是一个散列的引用,它是一个必须以'$'开头的标量。当你使用它时,你需要_dereference_它,所以'$ h - > {key}'等等。哈希以'%'开头。你直接访问它,'$ h {key}'。有关初学者,请参阅[perlreftut](http://perldoc.perl.org/perlreftut.html)。现在,代码是不正确的。 – zdim

+0

@JonBot这两个都允许你使用键值关联。关于hashref的一个更好的事情是它是一个标量,一个单值,对于传递给函数等来说更好。它就像一个C中的指针。但是使用它需要更多的语法。关于散列的一个更好的事情是,您直接使用数据结构,它在概念上更容易,并且在眼睛(和手)上更简单。然后有一些当然:) – zdim

0

该文件使用CR LF作为行尾。这将通过添加以下到您的代码变得很明显:

local $Data::Dumper::Useqq = 1; 

你可以将文件转换为使用Unix行结尾(看你是在UNIX系统上)。这可以使用dos2unix实用程序来实现。

dos2unix config.dat 

或者,用更灵活的

$line =~ s/\s+\z//; 

  • 注意更换

    chomp($line); 
    

    %product_names->{$words[0]}是没有意义的。它恰好在老版本的Perl中做了你想要的,但它在新版本中正确地抛出了一个错误。 $product_names{$words[0]}是访问哈希元素值的正确语法。

  • 提示:您应该使用print Dumper(\%product_names);而不是print Dumper(%product_names);
  • 提示:您也许会发现local $Data::Dumper::Sortkeys = 1;有用。数据::自卸车有这样糟糕的默认:(
  • 提示:使用的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 =~ /^#/;会避免很多的缩进
0

姆......这似乎我错了,即使你使用Perl6:

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

我不知道Perl6非常好,但在Perl5的参考应该像波纹考虑%product_names存在,并宣称:

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

如果你能露出完整的代码,我可以有助于解决这个问题。