将字符串内容eval到散列p时的陷阱错误

时间:2011-03-20 23:45:36

标签: perl warnings eval

我正在尝试将存储在字符串中的哈希定义转换为实际哈希。使用eval()函数可以很好地解决这个问题。

但是,我希望有可能在错误的哈希定义存储在字符串中时捕获错误。

为什么我不能捕获/捕获第9行中发生的错误?

#!/usr/bin/perl
use warnings;
use strict;

my $good_hash = "( 1 => 'one', 2 => 'two')";
my $bad_hash = "[ 1 => 'one', 2 => 'two')";

eval{my %string = eval($good_hash)} or &error;
eval{my %string = eval($bad_hash)} or &error;


sub error(){
        print "error\n";
}

5 个答案:

答案 0 :(得分:3)

你无法捕捉到“错误”,因为它只是一个警告,而不是错误。

您是否必须使用Perl哈希,或者您可以使用json,xml甚至Storable来存储数据吗?

答案 1 :(得分:3)

eval操作可能会抛出错误或警告。 来自eval的错误消息存储在$ @变量中。如果没有抛出错误,$ @将是一个空字符串。 但是,警告消息不会存储在$ @变量中。您可以使用$SIG{__WARN__}

处理警告

我认为在你的情况下,eval会发出警告。处理它的一种方法是做这样的事情:

#!/usr/bin/perl
use warnings;
use strict;

BEGIN { $SIG{'__WARN__'} = sub { error ($_[0]); }}

my $good_hash = "( 1 => 'one', 2 => 'two')";
my $bad_hash = "[ 1 => 'one', 2 => 'two')";

eval{my %string = eval($good_hash)}; error($@) if ($@);
eval{my %string = eval($bad_hash)};  error($@) if ($@);


# sub error will be called both in case of errors and warning.
sub error
{
    my ($msg ) = @_;
        print "Error/ warning message - $msg\n";
}

这是一个简单的代码示例,可以根据您的要求进行改进。

答案 2 :(得分:0)

更容易理解这一点的方法是记住eval执行表达式或代码块。给它一个完整的表达式会让事情更容易理解:

#!/usr/bin/perl
use warnings;
use strict;

my $good_hash = "\%string = ( 1 => 'one', 2 => 'two')";
my $bad_hash  = "\%string = [ 1 => 'one', 2 => 'two')";

my %string;

eval $good_hash;
if ($@) {
  error("can't process good_hash: $@");
}

eval $bad_hash;
if ($@) {
  error("can't process bad_hash: $@");
}

sub error {
  my $msg = shift;
  print "error: $msg\n";
}

请注意%string的预先声明,两个字符串如何包含完整的perl表达式以及我们如何查看$ @以查看实际错误是什么。

答案 3 :(得分:0)

您的错误子应该打印"error $@",因为$@(又名{EVAL_ERROR来自English)会告诉您eval结束了什么错误。您不能只打印字符串"error"并期望Perl知道您要打印错误。

答案 4 :(得分:-2)

我建议您在评估字符串之前使用正则表达式来测试字符串

类似的东西:

if($hash =~ /^\((\s?[a-z0-9]+\s?=>\s?'[a-z0-9]*'\s?,?)*\)$/){
eval{my %string = eval($hash)};
} else {&error;}

这也应该有助于防止执行无效输入,这可能会导致系统出现不良事件....