我正在尝试将存储在字符串中的哈希定义转换为实际哈希。使用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";
}
答案 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;}
这也应该有助于防止执行无效输入,这可能会导致系统出现不良事件....