Perl eval Data::Dumper 不一致
Perl eval Data::Dumper inconsistency
我必须在 Perl 中序列化和反序列化。我知道 Data::Dumper
和 eval
不是最适合这项工作的人,但我不允许在我正在处理的遗留脚本中修改这方面。
以下是使用 eval
.
的两种方式( CODE 1 和 CODE 2 )
在 CODE 1 中,散列在通过 eval
.
反序列化之前可作为字符串使用
在 CODE 2 中,散列在通过 eval
反序列化之前使用 Dumper
序列化。
在这两个代码示例中,两种尝试的反序列化方法中的一种有效。为什么反序列化的另一种方法不起作用?
代码 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;
]
但下面的代码以相反的方式工作:
代码 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
};
]
首先,请不要添加导致语法错误的注释(**
)。
请注意,您在第一个代码块中提供的字符串生成的数据结构与 Dumper 函数不同。在第一个块中,您创建了一个散列,但没有将其分配给任何变量。在 Dumper 函数的情况下,创建匿名散列并将其引用传递给 $VAR
变量。
要使第一个代码有效,您应该将 (
替换为 {
以创建匿名散列,然后将其分配给变量,例如:
my $r2 = "$VAR = {
'w' => {
'k2' => 5,
'k1' => 'key',
'k3' => [
'a',
'b',
2,
'3'
]
},
'q' => 2
}";
不要使用 Data::Dumper 序列化数据。话虽如此...
这是标量和列表上下文的问题。在第二次评估中,您有:
my $answer = ...;
由于您要分配给标量,因此右侧是在标量上下文中计算的。这意味着 eval
在标量上下文中。该值为:
(
'w' => {
'k2' => 5,
'k1' => 'key',
'k3' => [
'a',
'b',
2,
'3'
]
},
'q' => 2
)
这看起来像一个列表,但它实际上是标量上下文中的逗号运算符。评估左侧,丢弃该结果,returns 右侧。因此,my $x = ( 'left', 'right' )
将 right
分配给 $x
。 What is the difference between a list and an array? in 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'
];
我必须在 Perl 中序列化和反序列化。我知道 Data::Dumper
和 eval
不是最适合这项工作的人,但我不允许在我正在处理的遗留脚本中修改这方面。
以下是使用 eval
.
的两种方式( CODE 1 和 CODE 2 )
在 CODE 1 中,散列在通过 eval
.
反序列化之前可作为字符串使用
在 CODE 2 中,散列在通过 eval
反序列化之前使用 Dumper
序列化。
在这两个代码示例中,两种尝试的反序列化方法中的一种有效。为什么反序列化的另一种方法不起作用?
代码 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;
]
但下面的代码以相反的方式工作:
代码 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
};
]
首先,请不要添加导致语法错误的注释(**
)。
请注意,您在第一个代码块中提供的字符串生成的数据结构与 Dumper 函数不同。在第一个块中,您创建了一个散列,但没有将其分配给任何变量。在 Dumper 函数的情况下,创建匿名散列并将其引用传递给 $VAR
变量。
要使第一个代码有效,您应该将 (
替换为 {
以创建匿名散列,然后将其分配给变量,例如:
my $r2 = "$VAR = {
'w' => {
'k2' => 5,
'k1' => 'key',
'k3' => [
'a',
'b',
2,
'3'
]
},
'q' => 2
}";
不要使用 Data::Dumper 序列化数据。话虽如此...
这是标量和列表上下文的问题。在第二次评估中,您有:
my $answer = ...;
由于您要分配给标量,因此右侧是在标量上下文中计算的。这意味着 eval
在标量上下文中。该值为:
(
'w' => {
'k2' => 5,
'k1' => 'key',
'k3' => [
'a',
'b',
2,
'3'
]
},
'q' => 2
)
这看起来像一个列表,但它实际上是标量上下文中的逗号运算符。评估左侧,丢弃该结果,returns 右侧。因此,my $x = ( 'left', 'right' )
将 right
分配给 $x
。 What is the difference between a list and an array? in 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'
];