将字符串内容评估为哈希 p 时捕获错误

发布于 2024-10-24 02:11:42 字数 437 浏览 2 评论 0原文

我正在尝试将存储在字符串中的哈希定义转换为实际的哈希。这与 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";
}

I'm trying to transform a hash definition which is stored in a string to an actual hash. This works out great with the eval() function.

I want to however to have the possibility to trap errors when an faulty hash definition is stored in the string.

Why can't I catch/trap the error which occurs in line 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";
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

音栖息无 2024-10-31 02:11:42

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";
}

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

The eval operation can throw either errors or warnings.
The error messages from eval are stored in the $@ variable. If there was no error thrown , $@ will be an empty string.
However, warning messages are not stored in the $@ variable. You can process the warnings by using $SIG{__WARN__}.

I think in your case, eval is throwing warnings. One way of handling it would be by doing something like this:

#!/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";
}

This is simplistic code example and can be improved based on your requirement.

只为一人 2024-10-31 02:11:42

您无法捕获“错误”,因为它只是警告,而不是错误。

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

You can't catch the "error" because it's just a warning, not an error.

Do you have to use a Perl hash, or can you use json, xml, or even Storable to store the data?

维持三分热 2024-10-31 02:11:42

一种更简单的可视化方法是记住 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 表达式以及我们如何查看 $@ 以了解实际的错误是什么。

An easier way to visualise this is to remember that eval executes an expression or code block. Giving it a complete expression makes things a little bit easier to understand:

#!/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";
}

Note the pre-declaration of %string, how the two strings contain complete perl expressions and how we look at $@ to see what the actual error was.

寄风 2024-10-31 02:11:42

您的错误子应该打印 "error $@" 因为 $@ (又名 $EVAL_ERROR 通过 English) 告诉您是什么错误导致 eval 结束。您不能只打印出字符串 "error" 并期望 Perl 知道您想要打印错误。

Your error sub should print "error $@" because $@ (aka $EVAL_ERROR via English) tells you what error made the eval end. You can't just print out a string "error" and expect Perl to know that you want to print an error.

花之痕靓丽 2024-10-31 02:11:42

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

例如:

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

这也应该有助于防止执行无效的输入,这可能会导致系统上发生不好的事情......

I recommend that you use a regex to test the string before eval-ing it

something like:

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

This should also help to prevent invalid inputs from being executed which may cause bad things to happen on your system....

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文