Ошибки перехвата при вычислении содержимого строки в хэш - PullRequest
0 голосов
/ 21 марта 2011

Я пытаюсь преобразовать определение хеша, которое хранится в строке, в фактический хеш.Это прекрасно работает с функцией 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 ]

3 голосов
/ 21 марта 2011

Операция 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";
}

Это пример упрощенного кода, который можно улучшить в зависимости от ваших требований.

3 голосов
/ 21 марта 2011

Вы не можете поймать «ошибку», потому что это всего лишь предупреждение, а не ошибка.

Нужно ли использовать хэш Perl, или вы можете использовать json, xml или даже Сохраняем для хранения данных?

0 голосов
/ 21 марта 2011

Ваш саб ошибки должен вывести "error $@", потому что $@ (он же $ EVAL_ERROR через English) сообщает вам, какая ошибка привела к завершению eval. Вы не можете просто распечатать строку "error" и ожидать, что Perl будет знать, что вы хотите напечатать ошибку.

0 голосов
/ 21 марта 2011

Более простой способ визуализировать это - помнить, что 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 и как мы смотрим на $ @, чтобы увидеть, чтофактическая ошибка была.

0 голосов
/ 21 марта 2011

Я рекомендую использовать регулярное выражение для проверки строки перед ее проверкой

что-то вроде:

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

Это также должно помочь предотвратить выполнение неверных входных данных, что может привести к тому, что в вашей системе произойдут плохие вещи ...

...