2016-03-28 84 views
1

我必須在Perl中進行序列化和反序列化。我知道Data::Dumpereval不適合這份工作,但我不允許在我正在處理的舊腳本中修改這方面的內容。
使用eval有兩種方法(代碼1代碼2)。
CODE 1,在通過eval進行反序列化之前,散列可以以字符串形式提供。
CODE 2,在通過eval進行反序列化之前,使用Dumper對散列進行序列化。Perl eval Data :: Dumper不一致

在這兩個代碼示例中,兩種試圖反序列化作品的方法之一。爲什麼反序列化的另一種方式不起作用?

CODE 1

my $r2 = "( 
'w' => { 
      'k2' => 5, 
      'k1' => 'key', 
      'k3' => [ 
        'a', 
        'b', 
        2, 
        '3' 
        ] 
     }, 
    'q' => 2 
)"; 

my %z; 
eval "\%z = $r2";   ####### Works. 
print "\%z = [".Data::Dumper::Dumper (\%z)."] "; 

my $answer = eval "$r2"; #### Does NOT work. 
print "\n\nEvaled = [".Dumper($answer)."] "; 

輸出

%z = [$VAR1 = { 
      'w' => { 
        'k2' => 5, 
        'k1' => 'key', 
        'k3' => [ 
          'a', 
          'b', 
          2, 
          '3' 
          ] 
       }, 
      'q' => 2 
     }; 
] 

Evaled = [$VAR1 = 2; 
] 

但是下面的代碼工作以反轉方式:
CODE 2

my %a = ("q" =>2, "w"=>{ "k1"=>"key", "k2"=>5, k3=>["a", "b", 2, "3",], },); **# Same hash as above example.** 
$Data::Dumper::Terse=1; 
$Data::Dumper::Purity = 1; 
my $r2 = Dumper(\%a); 

my %z; 
eval '\%z = $r2'; 
print "\n\n\%z = [".Dumper(\%z)."] ";   #### Does NOT work. 

my $answer = eval $r2; 
print "\n\nEvaled = [".Dumper($answer)."] "; ####### Works. 

輸出

%z = [$VAR1 = {}; 
] 

Evaled = [$VAR1 = { 
      'w' => { 
        'k2' => 5, 
        'k1' => 'key', 
        'k3' => [ 
          'a', 
          'b', 
          2, 
          '3' 
          ] 
       }, 
      'q' => 2 
     }; 
] 

回答

2

首先,請不要把導致語法錯誤(**)的意見。

請注意,您在第一個代碼塊中提供的字符串會產生與Dumper功能不同的數據結構。在第一個塊中,您正在創建一個散列,但您不會將其分配給任何變量。在Dumper功能的情況下,創建匿名散列並將其引用傳遞給$VAR變量。

爲了使第一個代碼工作,你應該{取代(創建匿名哈希,然後將其分配給一個變量,例如:

my $r2 = "$VAR = { 
    'w' => { 
      'k2' => 5, 
      'k1' => 'key', 
      'k3' => [ 
        'a', 
        'b', 
        2, 
        '3' 
        ] 
     }, 
    'q' => 2 
}"; 
+0

感謝您的時間。目前,我正在使用模式匹配和替換來更改帶圓括號的前導和尾隨大括號。我們可以用其他方式做到嗎?另外,我刪除了星星。我應該把它們放在#後面。 – gsinha

+0

你不需要改變所有的數據。只是改變你做任務的方式。 –

1

不要使用數據::自卸車序列化數據。話雖如此......

這是一個標量和列表上下文的問題。在第二個評估中,您有:

my $answer = ...; 

由於您正在分配給標量,因此將在標量上下文中評估右側。這意味着eval處於標量環境。該值爲:

(
'w' => { 
      'k2' => 5, 
      'k1' => 'key', 
      'k3' => [ 
        'a', 
        'b', 
        2, 
        '3' 
        ] 
     }, 
    'q' => 2 
) 

看起來像一個列表,但它確實是標量上下文中的逗號運算符。評估左側,丟棄結果,並返回右側。所以,my $x = ('left', 'right')指定right$x。這在What is the difference between a list and an array?perlfaq4中進行了介紹。

在你的問題中,你會看到$r的值爲2。這是逗號鏈中最正確的值,所以這是您在標量上下文中獲得的價值。更改爲另一個值(也許'duck'),就是這樣,你會回來的值:

my $r2 = "(
    'w' => { 
       'k2' => 5, 
      }, 
     'q' => 'duck' 
    )"; 

my $answer = eval "$r2"; 

use Data::Dumper; 
print "Evaled =\n" . Dumper($answer); 

,因爲他們認爲這是某種形式的計數這不是一個數字,它混淆了人們:

Evaled = 
$VAR1 = 'duck'; 

改變,要在列表上下文分配(即哈希分配是一個列表賦值),你會得到正確的答案:

my $r2 = "(
    'w' => { 
       'k2' => 5, 
      }, 
     'q' => 'duck' 
    )"; 

my @answer = eval "$r2"; 

use Data::Dumper; 
print "Evaled =\n" . Dumper(\@answer); 

現在是你以爲的數據結構它應該是:

Evaled = 
$VAR1 = [ 
      'w', 
      { 
      'k2' => 5 
      }, 
      'q', 
      'duck' 
     ]; 
相關問題