perlcritic:eval"require $ module";

kob*_*ame 4 perl perl-critic

在挖掘一些旧的源代码时,我看到了以下内容:

my $module = $some{module};
eval "require $module";
die "Bad module\n$@" if $@;
Run Code Online (Sandbox Code Playgroud)

当我理解代码的作用时,它会尝试"需要"一个模块并在它不成功时死掉 - perlcritic抱怨它

第31栏第13栏"eval"的表达形式.参见PBP第161页.(严重程度:5)

不幸的是我没有PBP书,所以想知道上面的正确方法是什么...

此外,在相同的来源发现:

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

这里不明白什么解决了"eval",并且perlcritic再次抱怨"字符串评估"......

有人可以解释关于"字符串评估"的基本要点以及如何正确编写上述内容吗?

cho*_*oba 7

跑步perlcritic --verbose '%d\n'也会给你解释:

每次执行时都会重新编译`eval'的字符串形式,而块形式只编译一次.此外,字符串形式不提供编译时警告.

   eval "print $foo";        # not ok
   eval {print $foo};        # ok
Run Code Online (Sandbox Code Playgroud)

它适用于第一种情况.

第二种情况不会为我生成任何消息.不是吗?

return eval "-$test $abspath"
Run Code Online (Sandbox Code Playgroud)

你不能在这里使用块eval.您应该验证$ test是否真的包含它应该包含的内容

$test =~ /^[a-z]$/i
Run Code Online (Sandbox Code Playgroud)

并避免评估$ abspath:

eval "-$test \$abspath"
Run Code Online (Sandbox Code Playgroud)

如果你对它没问题,你可以添加

## no critic
Run Code Online (Sandbox Code Playgroud)

到最后一行.


ike*_*ami 5

很少有用户应该使用eval EXPR. 大多数情况下,它在不应该使用时(例如s/.../eval($repl)/e)被用作模板系统,或者在eval BLOCK应该使用时用于捕获异常。

如果有理由使用它,就是执行生成的代码或用户提交的代码。生成代码既棘手又容易出错,而且错误具有安全隐患。执行用户提交的代码是一个主要的安全问题。因此,eval EXPR应仔细审查每次使用。

perlcritic鉴于几乎每次使用都是具有重大安全隐患的错误,因此标记其使用是非常合适的。


在您的情况下,使用eval EXPR是次优的。我会用

my $path = $module . ".pm";
$path =~ s{::}{/}g;
eval { require $path }
Run Code Online (Sandbox Code Playgroud)

是的,这是便携式的。