Perl 为什么纯字符串可以用作文件句柄?

Perl 为什么纯字符串可以用作文件句柄?,perl,Perl,我知道bareword可以用作下面第一行的文件句柄,即使不推荐使用,但第二行似乎也可以。为什么纯字符串用作文件句柄 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与普通字符串“FH”相同,为什么下面的行不起作用 perl -E"open

我知道bareword可以用作下面第一行的文件句柄,即使不推荐使用,但第二行似乎也可以。为什么纯字符串用作文件句柄

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与普通字符串“FH”相同,为什么下面的行不起作用

perl -E"open FH, 'somefile.txt';print <'FH'>"
询问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>;

毕竟它不使用String而是Type,但是我不认为这是一个好的实践。

< P>询问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>;

毕竟它不使用字符串,但不考虑使用Type,但我不认为这是一个好的实践。

< P>如果没有Foo:< /P>子,以下两个语句是相同的。 因此,以下内容是等效的并不奇怪:

open FH, ...
open 'FH', ...
同样的道理也适用于

print { FH } ...
print { 'FH' } ...
以及

readline(FH)
readline('FH')
请注意,以下内容并不等同

print FH ...
print 'FH' ...
<FH>
<'FH'>
因为解析器专门查看是否提供了一个裸字来打印,以确定参数的含义

print LIST           # Prints list to selected handle
print BAREWORD LIST  # Prints list to specified handle
print { EXPR } LIST  # Prints list to specified handle
请注意,以下内容并不等同

print FH ...
print 'FH' ...
<FH>
<'FH'>
因为解析器专门查看一个裸字是否在其内部,以确定运算符的含义

<BAREWORD>   # readline(BAREWORD)
<EXPR>       # glob(EXPR)

如果没有子名为FOO,则以下两个语句是相同的:

因此,以下内容是等效的并不奇怪:

open FH, ...
open 'FH', ...
同样的道理也适用于

print { FH } ...
print { 'FH' } ...
以及

readline(FH)
readline('FH')
请注意,以下内容并不等同

print FH ...
print 'FH' ...
<FH>
<'FH'>
因为解析器专门查看是否提供了一个裸字来打印,以确定参数的含义

print LIST           # Prints list to selected handle
print BAREWORD LIST  # Prints list to specified handle
print { EXPR } LIST  # Prints list to specified handle
请注意,以下内容并不等同

print FH ...
print 'FH' ...
<FH>
<'FH'>
因为解析器专门查看一个裸字是否在其内部,以确定运算符的含义

<BAREWORD>   # readline(BAREWORD)
<EXPR>       # glob(EXPR)

该文件句柄实际上不是一个简单的字,而是一个glob类型。这与Perl如何在符号表中存储包变量有关。我不想讨论符号表及其工作方式,但这是Perl存储对开放文件句柄的引用的方式

使用开放栏时存在多个问题。。。。主要功能是将该类型的glob传递给子例程。想象一个子程序,其中我获取一个已经打开的文件,读取该文件,然后返回与正则表达式匹配的下一行。如何传入文件句柄

my $line = grep_me ( BAR, $regex );    # That doesn't quite work.
有一种方法是将对该类型glob的引用传递给标量变量,但语法晦涩难懂,相当混乱

Perl5最大的特性之一是引用的使用。如果您以前没有使用过Perl引用,请查看

尝试以下程序:

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是对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超出范围,文件句柄就会自动关闭。 由于文件句柄的作用域是词汇性的,因此它在文件本身之外不可用。想象一下,如果我有一个使用文件的模块,如果我使用OpenFoo…,那么该文件句柄可用于使用我的模块的程序。如果我使用open my$foo…,则使用我的模块的程序无法在不通过我的模块的情况下操作文件。
该文件句柄实际上不是一个简单的字,而是一个glob类型。这与Perl如何在符号表中存储包变量有关。我不想讨论符号表及其工作方式,但这是Perl存储对开放文件句柄的引用的方式

使用开放栏时存在多个问题。。。。主要功能是将该类型的glob传递给子例程。想象一个子程序,其中我获取一个已经打开的文件,读取该文件,然后返回与正则表达式匹配的下一行。如何传入文件句柄

my $line = grep_me ( BAR, $regex );    # That doesn't quite work.
有一种方法是将对该类型glob的引用传递给标量变量,但语法晦涩难懂,相当混乱

Perl5最大的特性之一是引用的使用。如果您以前没有使用过Perl引用,请查看

尝试以下程序:

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是对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超出范围,文件句柄就会自动关闭。 由于文件句柄的作用域是词汇性的,因此它在文件本身之外不可用。想象一下,如果我有一个使用文件的模块,如果我使用OpenFoo…,那么该文件句柄可用于使用我的模块的程序。如果我使用open my$foo…,则使用我的模块的程序无法在不通过我的模块的情况下操作文件。
Perl做了很多基于遗留原因和com的工作

适宜性。这并不意味着使用它是一个好主意——既为了代码的可维护性,也为了您自己的理智。的确!人们不应该使用这两种方法中的任何一种。停止使用globals,像其他地方一样使用词汇。谢谢。我会避免使用这些模式,只是想从语法和语法的角度来理解。@ikegami我一直很感激被纠正。这条消息也是。关于你的更新,没有人说裸字FH和字符串文字“FH”是一样的。正如您已经演示的和下面演示的那样,它们不是:perl-E'sub-foo{abc}print-foo.\n.foo.\n;'。如果找不到其他含义,则一个裸字仅充当字符串文字。在您询问的特定情况下,Perl检查是否提供了一个裸字来确定是否意味着readline。。。或全球。。。。更新了我的答案。Perl做了很多基于遗留原因和兼容性而存在的事情。这并不意味着使用它是一个好主意——既为了代码的可维护性,也为了您自己的理智。的确!人们不应该使用这两种方法中的任何一种。停止使用globals,像其他地方一样使用词汇。谢谢。我会避免使用这些模式,只是想从语法和语法的角度来理解。@ikegami我一直很感激被纠正。这条消息也是。关于你的更新,没有人说裸字FH和字符串文字“FH”是一样的。正如您已经演示的和下面演示的那样,它们不是:perl-E'sub-foo{abc}print-foo.\n.foo.\n;'。如果找不到其他含义,则一个裸字仅充当字符串文字。在您询问的特定情况下,Perl检查是否提供了一个裸字来确定是否意味着readline。。。或全球。。。。更新了我的答案。这很奇怪。我本来打算评论说,使用我的$x=FOO将发出一个赤裸裸的警告,但事实并非如此。但是,我的$x=foo确实发出了警告。这是不一致的,大概是一些遗留物?不是我的downvote@TLP,警告不是针对将裸字用作字符串,而是针对一般情况下使用小写裸字,因为它们是Perl保留的。至少是正式的。实际上,需要一个特性来添加一个新名称,包括所有名称空间(小写或非小写)。这一警告应该取消。使用严格;这就禁止将裸字作为字符串。@ikegami似乎解析器可以识别裸字,并根据特定的上下文有不同的规则来处理它。在大多数一般的上下文中,它被转换为字符串,并在其他一些上下文中进行特定处理,比如它是print的第一个参数,或者是inside操作符。是这样吗?是的,没错。看看它们在默认情况下是如何执行相同的函数的,如果没有理由这样做,最好在其他上下文中保留这种关系,例如open的第一个参数。这很奇怪。我本来打算评论说,使用我的$x=FOO将发出一个赤裸裸的警告,但事实并非如此。但是,我的$x=foo确实发出了警告。这是不一致的,大概是一些遗留物?不是我的downvote@TLP,警告不是针对将裸字用作字符串,而是针对一般情况下使用小写裸字,因为它们是Perl保留的。至少是正式的。实际上,需要一个特性来添加一个新名称,包括所有名称空间(小写或非小写)。这一警告应该取消。使用严格;这就禁止将裸字作为字符串。@ikegami似乎解析器可以识别裸字,并根据特定的上下文有不同的规则来处理它。在大多数一般的上下文中,它被转换为字符串,并在其他一些上下文中进行特定处理,比如它是print的第一个参数,或者是inside操作符。是这样吗?是的,没错。在默认情况下,看到它们如何执行相同的函数,最好在其他上下文中保留该关系,例如,如果没有理由这样做,则保留open的第一个参数。Re如何传入文件句柄*酒吧有一种方法是将对该类型glob的引用传递给标量变量,但语法晦涩难懂,相当混乱。或者您可以只传递glob,它的语法与其他所有变量sigil+name相同。Re如何传递文件句柄*酒吧有一种方法是将对该类型glob的引用传递给标量变量,但语法晦涩难懂,相当混乱。或者您可以只传递glob,它的语法与其他所有变量sigil+name相同。