2015-04-15 1 views
4

При копании в каком-то старом исходном коде я увидел следующее:

my $module = $some{module}; 
eval "require $module"; 
die "Bad module\[email protected]" if [email protected]; 

в то время как я понимаю, что делает этот код, он пытается «требовать» модуль и умирают, когда он неудачно - perlcritic жалуется на это

Выражение «eval» по строке 331, столбец 13. См. Стр. 161 из PBP. (Серьезность: 5)

К сожалению, я нету книги PBP, так интересно, что это правильный метод выше ...

Кроме того, в том же источнике найдено:

sub test_repo_file { 
    my($self, $repo, $test) = @_; 
    my $abspath = repo_abs_path($repo); 
    return "eval -$test $abspath"; 
} 

Здесь не понимается, что решает «eval», а perlcritic снова жалуется на «string eval» ...

Может кто-нибудь объяснить основные моменты о «строке eval» и как правильно написать выше ?

ответ

7

Запуск perlcritic --verbose '%d\n' даст вам объяснение, тоже:

строковой формы `Eval» перекомпилируется каждый раз, когда она выполняется, в то время как виде блока только компилируются один раз. Кроме того, строка не дает предупреждений времени компиляции.

eval "print $foo";  # not ok 
    eval {print $foo};  # ok 

Это применимо к первому случаю.

Второй случай не генерирует никаких сообщений для меня. Разве это не

return eval "-$test $abspath" 

Здесь вы не можете использовать блок eval. Вы должны убедиться, что $ тест действительно содержит то, что он должен

$test =~ /^[a-z]$/i 

и избежать оценки $ abspath:

eval "-$test \$abspath" 

Если вы в порядке с этим, вы можете чем добавить

## no critic 

до конца строки.

3

Немногие пользователи должны когда-либо использовать eval EXPR. В большинстве случаев он используется как система шаблонов, если он не должен (например, s/.../eval($repl)/e), или используется для исключения исключений, когда должно было использоваться eval BLOCK.

Если есть основания для его использования, это необходимо выполнить сгенерированный код или код пользователя. Генерирование кода является сложным и подверженным ошибкам, а ошибки имеют последствия для безопасности. Выполнение пользовательского кода является серьезной проблемой безопасности. Таким образом, каждое использование eval EXPR должно быть тщательно проверено.


В вашем случае, использование eval EXPR является неоптимальным. Я бы использовал

my $path = $module . ".pm"; 
$path =~ s{::}{/}g; 
eval { require $path } 

Да, это портативный.