2016-03-28 40 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' 
     ];