5

如果这个问题听起来很简单,我深表歉意,我的目的是深入了解这个(这些?)特定运算符是如何工作的,我无法在 perldocs 中找到令人满意的描述(它可能存在于某个地方,我只是不能为我的一生找到它)

特别是,我有兴趣知道是否

一种)<>

b)<*>或任何全局和

C)<FH>

本质上相似或不同,以及它们如何在内部使用。

我构建了自己的测试函数来对此有所了解(如下所示)。我仍然没有完全理解(我的理解甚至可能是错误的),但这就是我得出的结论:

  • <>
    • 在标量上下文中:读取正在读取的“当前文件”的下一行(在 @ARGV 中提供)。问题:这似乎是一个非常特殊的场景,我想知道为什么会这样,以及它是否可以概括。还有什么是正在读取的“当前文件”?它在文件句柄中吗?什么是柜台?
    • 在列表上下文中:将@ARGV 中的所有文件读入一个数组
  • <list of globs>
    • 在标量上下文中:在当前文件夹中找到的与 glob 匹配的第一个文件的名称。问题: 为什么是当前文件夹?我该如何改变?改变这种情况的唯一方法是像 < /home/* > 吗?
    • 在列表上下文中:与当前文件夹中的 glob 匹配的所有文件。
  • <FH>分配给变量时似乎返回 undef 。 问题:为什么是undef?它没有类型吗?当 FH 不是裸字文件句柄时,这种行为是否类似?

一般问题:在执行期间处理 <> 的值和其他值的是什么?在标量上下文中,是否返回了任何类型的引用,或者我们分配它们的变量是否与任何其他非引用标量相同?

我还注意到,即使我按顺序分配它们,每次都会重置输出。即我会假设当我这样做时

$thing_s = <>;
@thing_l = <>;

@thing_l将丢失第一个项目,因为它已经由$thing_s. 为什么不是这样?

用于测试的代码:

use strict;
use warnings;
use Switch;
use Data::Dumper;

die "Call with a list of files\n" if (@ARGV<1);
my @whats = ('<>','<* .*>','<FH>');
my $thing_s;
my @thing_l;
for my $what(@whats){
    switch($what){
                    case('<>'){
                        $thing_s = <>;
                        @thing_l = <>;
                    }
                    case('<* .*>'){
                            $thing_s = <* .*>;
                            @thing_l = <* .*>;
                    }
                    case('<FH>'){
                            open FH, '<', $ARGV[0];
                            $thing_s = <FH>;
                            @thing_l = <FH>;
                    }

    }
    print "$what in scalar context is: \n".Dumper($thing_s)."\n";
    print "$what in list context is: \n".Dumper(@thing_l)."\n";
}
4

2 回答 2

12

这些<>东西都是迭代器。所有这些变体都有共同的行为:

  • 在列表上下文中使用时,将返回所有剩余元素。
  • 在标量上下文中使用,仅返回下一个元素。
  • 在标量上下文中使用,undef一旦迭代器耗尽,它就会返回。

最后两个属性使其适合用作while循环中的条件。

有两种迭代器可以与 一起使用<>

  • 文件句柄。在这种情况下<$fh>相当于readline $fh
  • Globs,so<* .*>等价于glob '* .*'.

<>它不包含任何内容、裸字或简单标量时,它被解析为 readline。可以嵌入更复杂的表达式,如<{ ... }>.

在所有其他情况下,它都被解析为一个 glob。这可以通过使用引号来明确表示:<"* .*">但您应该真正明确并使用该glob函数。

一些细节有所不同,例如迭代器状态的保存位置:

  • 从文件句柄读取时,文件句柄保持该迭代器状态。
  • 使用 glob 形式时,每个 glob 表达式都有自己的状态。

另一部分是迭代器是否可以重新启动:

  • glob 在返回一个后重新启动undef
  • 文件句柄只能通过查找重新启动——并非所有 FH 都支持此操作。

如果在 中没有使用文件句柄<>,则默认为特殊ARGV文件句柄。的行为<ARGV>如下:

  • 如果@ARGV为空,ARGV则为STDIN
  • 否则, 的元素将@ARGV被视为文件名。执行以下伪代码:

    $ARGV = shift @ARGV;
    open ARGV, $ARGV or die ...; # careful! no open mode is used
    

    $ARGV量保存文件名,ARGV文件句柄保存该文件句柄。

  • When ARGVwould be eof,打开下一个文件@ARGV
  • 只有@ARGV完全空了才能<>返回undef

这实际上可以用作从许多文件中读取的技巧:

local @ARGV = qw(foo.txt bar.txt baz.txt);
while (<>) {
  ...;
}
于 2013-09-17T20:28:07.793 回答
4

在执行过程中处理值<>和其他值的是什么?

Perl 编译器具有很强的上下文感知能力,并且经常不得不在代码段的多个模棱两可的解释之间进行选择。它将编译<>为调用readline或调用,glob具体取决于括号内的内容。

在标量上下文中,是否返回了任何类型的引用,或者我们分配它们的变量是否与任何其他非引用标量相同?

我不确定你在这里问什么,或者为什么你认为得到 a 结果的变量<>应该与其他变量不同。它们总是简单的字符串值:要么是返回的文件名glob,要么是返回的一些文件数据readline

<FH>分配给变量时似乎返回 undef 。问题:为什么是undef?它没有类型吗?当 FH 不是裸字文件句柄时,这种行为是否类似?

此表单将被FH视为文件句柄,如果文件打开且不在 eof 处,则返回文件的下一行数据。否则undef返回,以指示无法读取任何有效内容。Perl 在类型方面非常灵活,但undef表现为它自己的类型,就像 Ruby 的nil. FH无论是全局文件句柄还是(包含的变量)对 typeglob 的引用,运算符的行为都是相同的。

于 2013-09-17T20:25:54.253 回答