【问题标题】:Why does ${fh} behave differentially than $fh when reading line by line?为什么在逐行读取时 ${fh} 的行为与 $fh 不同?
【发布时间】:2016-01-16 10:48:14
【问题描述】:

这个脚本:

#!/usr/bin/perl
use strict;
use warnings;

my ${fh};

open($fh, '<', "some_file.txt") or die "fail\n";

while(my $line = <${fh}> ) {
    print $line;
}
close $fh;

输出:

GLOB(0x5bcc2a0)

为什么是这个输出?

如果我将&lt;${fh}&gt; 更改为&lt;$fh&gt;,它将按预期逐行打印some_file.txt。我认为大括号可以用来分隔变量名,并且my ${var} 将与my $var 相同。

在变量名周围添加{} 是否会导致问题?

我在 Red Hat 和 Cygwin Perl 5.14 上尝试了 Perl 5.8.8。

【问题讨论】:

  • 在很多情况下添加{}会改变解析,例如"$foobar""${foo}bar""$foo::bar""${foo}::bar""$foo's bar""${foo}'s bar""$foo[0]""${foo}[0]"。但我猜你问的是字符串插值以外的情况?
  • @ThisSuitIsBlack 不是你猜对的。答案也很好!

标签: perl


【解决方案1】:

来自perlop中的&lt;&gt;部分:

如果尖括号包含的是一个简单的标量变量(例如,$foo),那么该变量包含要输入的文件句柄的名称,或其类型团,或对相同的引用。例如:

$fh = \*STDIN;
$line = <$fh>;

如果尖括号中的内容既不是文件句柄,也不是包含文件句柄名称、typeglob 或 typeglob 引用的简单标量变量,则将其解释为要通配的文件名模式,以及文件名列表或下一个文件名根据上下文返回列表中的。这种区别仅由句法基础决定。这意味着&lt;$x&gt; 始终是来自间接句柄的readline(),但&lt;$hash{key}&gt; 始终是glob()。那是因为$x 是一个简单的标量变量,但$hash{key} 不是——它是一个哈希元素。即使&lt;$x &gt;(注意多余的空格)也被视为glob("$x "),而不是readline($x)

你可以通过B::Concise看到这个:

$ perl -MO=Concise -e'<$fh>'
5  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 1 -e:1) v:{ ->3
4     <1> readline[t1] vK*/1 ->5
-        <1> ex-rv2sv sK/1 ->4
3           <$> gvsv(*fh) s ->4
-e syntax OK

$ perl -MO=Concise -e'<${fh}>'
6  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 70 -e:1) v:{ ->3
5     <@> glob[t1] vK/1 ->6
-        <0> ex-pushmark s ->3
-        <1> ex-rv2sv sK/1 ->4
3           <$> gvsv(*fh) s ->4
4        <$> gv(*_GEN_0) s ->5
-e syntax OK

【讨论】:

    【解决方案2】:
    • &lt;&gt; 表示 readline(ARGV)
    • &lt;IDENTIFIER&gt; 表示 readline(IDENTIFIER)
    • &lt;$IDENTIFIER&gt; 表示 readline($IDENTIFIER)
    • &lt;...&gt;(其他)表示glob(qq&lt;...&gt;)

    所以,

    • &lt;$fh&gt; 表示 readline($fh)
    • &lt;${fh}&gt; 表示glob(qq&lt;${fh}&gt;),与glob("$fh") 相同。

    glob 用于从模式中生成多个字符串或文件名。

    在这种情况下,文件句柄的字符串化为GLOB(0x5bcc2a0)。这被传递给 glob,但这些字符中没有一个对 glob 有特殊含义,因此 glob 只返回该字符串。

    【讨论】:

    • 所以基本上&lt;&gt; 是在完全字符级别定义的......哇,CS 不及格的工作!
    • @Kaz,你从哪里得到的?我的帖子用代币来定义它。即使它确实使用了一种子语言(例如m//tr///sprintfglob),我也不明白为什么这会让你的短裤打结。
    • 在另一个答案中指出(引用自文档)即使&lt;$x &gt; 也与&lt;$x&gt; 完全不同。
    • @Kaz,也在这个答案中。所以呢?为什么要提这个?
    • @nwellnhof,你似乎只读了我的一半,因为我特别说过这不是你穿短裤的原因,因为它一直在发生。 /$x//$x / 不同。 "$x""$x " 不同。等
    猜你喜欢
    • 1970-01-01
    • 2011-08-01
    • 2011-09-08
    • 1970-01-01
    • 2022-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-08
    相关资源
    最近更新 更多