我理解裸字可以用作文件句柄作为下面的第一行,即使不推荐它,但似乎第二行也可以。为什么普通字符串可以作为文件句柄工作?
perl -E"open FH, 'somefile.txt' or die 'open failed';print <FH>"
perl -E"open 'FH', 'somefile.txt' or die 'open failed';print <FH>"
更新:如果裸字FH与普通字符串&#39; FH&#39;相同,为什么以下行不起作用?
perl -E"open FH, 'somefile.txt';print <'FH'>"
答案 0 :(得分:5)
以下两个陈述是相同的(如果没有名为FOO
的子词):
my $x = FOO;
my $x = 'FOO';
因此,以下内容并非如此令人惊讶:
open FH, ...
open 'FH', ...
同样如此
print { FH } ...
print { 'FH' } ...
和
readline(FH)
readline('FH')
请注意,以下内容不等同
print FH ...
print 'FH' ...
因为解析器专门查看是否为print
提供了一个裸字来确定参数的含义。
print LIST # Prints list to selected handle
print BAREWORD LIST # Prints list to specified handle
print { EXPR } LIST # Prints list to specified handle
请注意,以下内容不等同
<FH>
<'FH'>
因为解析器专门查看一个裸字是否在<>
内,以确定运算符的含义。
<BAREWORD> # readline(BAREWORD)
<EXPR> # glob(EXPR)
答案 1 :(得分:4)
询问perl解析器,
perl -MO=Deparse -E"open 'FH', 'somefile.txt' or die 'open failed';print <FH>"
use feature 'current_sub', 'evalbytes', 'fc', 'say', 'state', 'switch', 'unicode_strings', 'unicode_eval';
die 'open failed' unless open *FH, 'somefile.txt';
print <FH>;
所以它毕竟不使用字符串而是使用typeglob,但我认为这不是一个好习惯。
答案 2 :(得分:2)
该文件句柄不是裸词,而是类型glob 。这与Perl如何在符号表中存储包变量有关。我不想进入符号表以及它们是如何工作的,但它是Perl可以存储对打开文件句柄的引用的方式。
使用open BAR...
存在多个问题。主要的是能够将类型glob 传递给子例程。想象一个子程序,我在其中取一个已经打开的文件,读取该文件,然后返回与正则表达式匹配的下一行。如何传入文件句柄?
my $line = grep_me ( BAR, $regex ); # That doesn't quite work.
通过将类型glob 的引用传递给标量变量, 是一种方法,但语法模糊而且相当混乱。
Perl 5中最大的功能之一是使用引用。如果您之前没有使用过Perl参考,请查看tutorial。
试试这个程序:
use strict;
use warnings;
use feature qw(say);
my $real_file = "..."; # A real file with that name
open my $foo, "<", $real_file or die $!;
say "\$foo is a $foo";
这将打印出如下内容:
$foo is a GLOB(0x7feb0c0060e8)
这就是说$foo
是类型glob 的引用。记得我说你可以通过引用它来将类型的glob 文件句柄传递给子程序吗? Perl 5已经为您提供了很好的引用,这使得传递该文件的句柄变得非常简单:
...
my $line = grep_me ( $foo, $regex );
...
sub grep_me {
my $fh = shift; # The file handle
my $re = shift; # The regular expression
my $line;
while ( $line = <$fh> ) {
last if ( $line =~ /$re/ );
}
return $line;
}
使用标量引用也有其他优点:
$foo
超出范围,文件句柄就会自动关闭。open FOO...
,该文件句柄可用于使用我的模块的程序。如果我使用open my $foo...
,则使用我的模块的程序无法通过我的模块操作文件。