为什么使用自动生成文件句柄的三参数打开调用是Perl的最佳实践?

Mor*_*nar 45 perl file-io scope

我有两个关于Perl open函数的问题:

1)我似乎记得Perl最佳实践中的3参数版本open比两个参数版本更好,例如

open(OUT, '>>', $file);
Run Code Online (Sandbox Code Playgroud)

open(OUT, ">>$file");
Run Code Online (Sandbox Code Playgroud)

这是为什么?我试图告诉别人前几天使用3参数版本,但似乎无法用任何东西支持它.

2)我似乎还记得autovivified文件句柄比bareword文件句柄更受青睐(他们称之为不同的东西)?而且也记不住为什么,例如

open(my $out, '>>', $file);
Run Code Online (Sandbox Code Playgroud)

open(OUT, '>>', $file);
Run Code Online (Sandbox Code Playgroud)

这是strict件事吗?我似乎记得能够使用OUT,strict但我不记得了.

Mar*_*rkR 64

  • 使用typeglobs作为文件句柄(例如OUT)不是一个好主意,因为它们在整个程序中是全局的 - 您需要确保没有其他例程(包括模块中的例程)使用相同的名称(包括将来).
  • 使用双参数形式的open将您的应用程序暴露给由包含特殊字符的变量引起的错误行为,例如my $f; open $f, ">$some_filename";,暴露于$some_filename包含前导的bug >会改变程序的行为.

使用三参数形式通过将模式和文件名分离为不能干涉的单独参数来避免这种情况.

此外,使用带有管道的大量参数形式是一个非常好的主意:

open $pipe, '|-', 'sendmail', 'fred@somewhere.fake';
Run Code Online (Sandbox Code Playgroud)

比将它作为单个字符串更好 - 它避免了可能的shell注入等.

  • 关于兼容性的注意事项:3-arg open和`open my $ fh,...`工作从5.6.0开始.`打开我的$ fh,'| - ',LIST`(列表管道打开)从5.8.0开始工作. (3认同)

mob*_*mob 16

解决#2:

OUT 是一个全局文件句柄,并使用它暴露你这样的阴险错误:

sub doSomething {
  my ($input) = @_;
  # let's compare $input to something we read from another file
  open(F, "<", $anotherFile);
  @F = <F>; 
  close F;
  &do_some_comparison($input, @F);
}

open(F, "<", $myfile);
while (<F>) {
    &doSomething($_);   # do'h -- just closed the F filehandle
}
close F;
Run Code Online (Sandbox Code Playgroud)


dla*_*and 13

要记住的一个方面是两个arg形式被打破.考虑一个名为"abc"的文件(即带有前导空格的文件名).你无法打开文件:

open my $foo, ' abc' or die $!;
open my $foo, '< abc' or die $!;
open my $foo, '<  abc' or die $!;
# nothing works
Run Code Online (Sandbox Code Playgroud)

空间被删除,因此无法再找到该文件.这种情况非常不可能,但绝对是一个问题.三个arg形式免疫这个:

open my $foo, '<', ' abc' or die $!;
# works
Run Code Online (Sandbox Code Playgroud)

来自perlmonks的这个帖子与任何问题一样好.请记住,在2001年,三arg形式仍然被认为是新的,因此不适用于可移植代码,因为如果在5.005解释器上运行,Perl程序将因语法错误而死亡.现在不再是这种情况了:perl 5.005已被弃用,已经过时了.

  • 不,这个问题的两个论证形式,或者一个论证形式,是*没有被打破.它按设计,记录和广告的方式工作.它可能只是*魔术开放*不是你需要的.三个参数打开的另一个插件是中间参数可以 - 通常应该 - 包括流的编码. (16认同)