Perl:打开还是[代码块]?

Posted

技术标签:

【中文标题】Perl:打开还是[代码块]?【英文标题】:Perl: open or [block of code]? 【发布时间】:2017-07-31 16:30:19 【问题描述】:

我正在运行脚本 A,它将包含文件路径的 ARGV 提供给 perl 脚本 B。这是由

local @ARGV = ($file, $file2, etc.);
do scriptB.pl or die "scriptB has failed";

脚本 B 然后尝试打开文件:

open( my $fh_file, "<", $file )  
  or die "Could not open file '$file' $!"; 

但是,如果文件丢失,我不会在 B 中的“or die”之后得到引用的消息。相反,我会在 A 中得到 do scriptB.pl or die 消息。如果我从 A 中删除“or die”,脚本在 B 无声无息地死后继续执行,就好像没有出错一样。

我想知道是否有任何方法可以让 B 打印它的 die 消息?

更好的是,让 B 在无法打开文件后运行代码块的最佳方法是什么?例如,所述代码将写入一个单独的文件,列出丢失的文件,以便用户可以轻松追踪此类错误。

#something like
open( my $fh_file, "<", $file) or  
print "the file could not be found";
die;

我发现在网上搜索帮助的唯一一件事是有人提到“或做”,但这给了我奇怪的语法错误,所以我不确定我是否正确使用它。

【问题讨论】:

“这给了我奇怪的语法错误” 请揭示这些奇怪的错误是什么,并显示产生它们的代码。 注意open ... or do ... ;中的块后面需要一个分号 你需要在scriptB.pl 周围加上引号(如果你是use strict,你应该这样做):do "scriptB.pl" or do if ( $@) ... else die $! ; 【参考方案1】:

如果您想继续使用open(...) or ... 语法,那么您可以使用do

open my $fh, '<', $file or do 
  ...
;

但我认为切换到if可能更清楚

if (! open my $fh, '<', $file) 
  ...

甚至unless

unless (open my $fh '<', $file) 
  ...

【讨论】:

因提供三个非常好的选项而受到支持。我不确定or do ... 语法是否不太清晰,因为它建立在人们(可能?希望?)已经习惯于看到的常见or die 模式之上。 当然。维护程序员的眼中是清晰 :-) 但至少语法错误的可能性大大增加,因为人们忘记了结束分号。 拒绝接受or do print(STDERR "...: $!\n"; die "ignored message"; ; 作为or die "...: $!\n" 的可接受替代方案。这种做法不应该采取!!!【参考方案2】:

我认为,如果您将脚本 B 放入模块中,并使用 userequire 加载它并使用明确的参数直接调用其中的函数,我认为您将获得更清晰的代码和更少的陷阱。

您在这里缺少的是do 在幕后涉及eval,这会导致异常混淆。您可以通过将脚本 B 代码移动到模块中的函数中并调用它,或多或少地避免这种混淆。

(此外,perl 5.26 将与 do 有轻微的打嗝,其中当前目录将从目录查找中删除,出于安全考虑。userequire 有相同的打嗝,但这可能是不那么令人惊讶,因为您应该将模块放入您明确进入 @INC 加载路径的路径中。)

【讨论】:

【参考方案3】:

die 不打印消息; die 抛出异常。当您捕获该异常时,您不会对传递给die 的消息执行任何操作。替换

local @ARGV = ($file, $file2, etc.);
do scriptB.pl or die "scriptB has failed";

local @ARGV = ($file, $file2, etc.);
do scriptB.pl or die "scriptB has failed: ". ( $@ || $! );

【讨论】:

以上是关于Perl:打开还是[代码块]?的主要内容,如果未能解决你的问题,请参考以下文章

如何在调试器下运行perl代码块?

Print语句在perl的外部块中打印两次

在 Perl 中打开和读取文件的最佳方法是啥?

Perl 学习记录

Perl unless

Java 代码块,普通代码块,构造代码块,静态代码块