LINUX.ORG.RU

Подскажите по perl

 


0

1

Да, недавно был подобный топик, я покопался, думал что все понял и снес, оказалось что понял, но как это в perl реализовать не понял.
Имеется скрипт для разбора бинарных ama файлов от iskra si3000, но с теми файлами что еть у меня он не работает, ругается на енсущнствующие block:

Undefined subroutine &CDR::Parser::SI3000::block_124 called at /usr/local/share/perl/5.32.1/CDR/Parser/SI3000.pm line 597.

Кусок кода, который возвращает ошибку:
my $block_marker;
 while( length($variable) > 0) {
 ($block_marker, $variable) = unpack('C a*', $variable);
 {
  no strict 'refs';
  my $sub = 'block_' . $block_marker;
  $sub->(\%call, \$variable);
 }
}

Как я понимаю, тут имя вызываемой функции происходит из объединения двух текстовых переменных. И если в бинарнике есть номер блока, который скрипту неизвестен то возвращается ошибка. Получается что мне нужно сделать обработку (игнорирование) ошибки при вызове $sub->(\%call, \$variable);. Кто может подсказать как сделать в perl, своими силами искал до ничего не понял.

★★★★★

Я никогда не писал на перле, но может так поможет?

my $block_marker;
 while( length($variable) > 0) {
 ($block_marker, $variable) = unpack('C a*', $variable);
 {
  no strict 'refs';
  my $sub = 'block_' . $block_marker;
  try {
    $sub->(\%call, \$variable);
  } catch {
    warn "caught error: $_";
  }
 }
}

romanlinux ★★★
()
Ответ на: комментарий от romanlinux

Действительно оно, только модуль подгрузить потребовалось use Try::Tiny. Спасибо!

Kolins ★★★★★
() автор топика

Сабрутин с block_122 по block_126 нету в пакете - https://metacpan.org/dist/CDR-Parser-SI3000/source/lib/CDR/Parser/SI3000.pm#L...

Тебе надо игнорировать эту ошибку (если, конечно ее надо игнорировать).

Попробуй код, где у тебя вызывается этот парсер, обернуть в eval с перехватом только этой ошибки:


my $result;

eval {
    $result = <вызов парсера>;
    1;
};

if ( my $error = $@ ) {
    if ( $error =~ /Undefined subroutine/i ) {
        warn $error;
    } else {
        die $error;
    }
}
KernelPanic
()
Последнее исправление: KernelPanic (всего исправлений: 4)

как вариант: узнать определена ли нужная функция

if (defined(&$sub)) {
   $sub->(\%call, \$variable);
}
$sub->(\%call, \$variable) if (defined(&$sub));
futurama ★★★★★
()
Последнее исправление: futurama (всего исправлений: 2)

В perl есть удобный оператор «//»

    my $sub = 'block_' . $block_marker // sub { print "Error" };
soomrack ★★★★★
()
Ответ на: комментарий от futurama

Выглядеть элегантнее, чем просто игнорировать ошибки, но почему-то не работает:

Invalid type '-' in unpack at /usr/local/share/perl/5.32.1/CDR/Parser/SI3000.pm line 459.

Kolins ★★★★★
() автор топика
Ответ на: комментарий от KernelPanic

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

Kolins ★★★★★
() автор топика
Ответ на: комментарий от Kolins

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

Try::Tiny - это всего лишь тонкая обертка над блоком eval { } и переменной $@

annulen ★★★★★
()
Последнее исправление: annulen (всего исправлений: 1)
Ответ на: комментарий от futurama

Посмотрел что на 459, тоже непонятно

459     ($stats,$$var) = unpack("a$len a*", $$var);


Если интересно покопаться код есть тут: https://github.com/sergle/CDR-Parser-SI3000/blob/master/lib/CDR/Parser/SI3000.pm, меня пока варинт с try-catch устраивает в принципе

Kolins ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.