我使用下面的脚本附加两个文件,它间歇性地无法附加没有错误输出.
(my $file1, my $file2) = @ARGV;
open(FILE1, ">>$file1");
open(FILE2, "<$file2");
while ( <FILE2> ) {
print FILE1 $_;
}
close(FILE2);
close(FILE1);
Run Code Online (Sandbox Code Playgroud)
上面的代码有什么问题吗?
您的代码的主要问题是它包含许多可能会失败的操作,但您没有检查错误,因此如果发生故障,程序将默默地尝试继续执行.
您的代码中可能会失败的三个函数是open,print和close.在每种情况下,函数将在成功时返回真值,或者在发生故障时返回false值,并将故障消息存储在特殊全局变量中$!.
你写:
open(FILE1,">>$file1");
Run Code Online (Sandbox Code Playgroud)
那会写得更好:
open(my $out, '>>', $file1) || die "open(>>$file1): $!";
Run Code Online (Sandbox Code Playgroud)
或者您可以使用较低优先级or运算符并跳过括号:
open my $out, '>>', $file1 or die "open(>>$file1): $!";
Run Code Online (Sandbox Code Playgroud)
您可以简单地调用,die $!但这会给您一个错误消息,Permission denied并且不会告诉您哪个操作失败(尽管die会添加发生故障的行号).有时失败是由于包含文件名的变量在其中有意外的事实 - 所以打印出来也是一个好习惯.
您的代码包含一些相当旧的样式,因此我FILE1用词法范围替换旧样式全局$out.我还使用了3参数形式的open,从安全角度来看这是一个更好的主意.
该print电话还可能失败(例如:如果你的硬盘填补了).这种可能性较小,检查返回值print往往被忽视.该close电话还可能失败(例如:直到关闭文件句柄,然后像磁盘已满的情况可能会引发故障输出缓冲器可能不会得到刷新).
记住or die "... $!"在所有I/O函数调用结束时添加有点单调乏味,所以更好的方法是autodie在脚本开头将pragma 添加到样板.然后您可以省略显式错误检查,autodie模块将为您生成消息:
use strict;
use warnings;
use autodie;
my($file1, $file2) = @ARGV;
open my $out, '>>', $file1;
open my $in, '<', $file2;
while (<$in>) {
print $out $_;
}
close($in);
close($out);
Run Code Online (Sandbox Code Playgroud)
来自autodie的典型消息可能是:
Can't open '/etc/shadow' for reading: 'Permission denied' at ./ptst.pl line 8
Run Code Online (Sandbox Code Playgroud)
这告诉您哪个操作失败,参数是什么以及失败的原因.因此,通过使用autodie您可以获得更好的错