2016-09-30 95 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{...} = ... ; 

如果你能露出完整的代碼,我可以有助於解決這個問題。

相關問題