18

Perl 提供了这个非常好的特性:

while ( <> )
{
    # do something
}

...这允许使用脚本script.pl <filename>以及cat <filename> | script.pl.

现在,有没有办法确定脚本是否以前一种方式被调用,如果是,文件名是什么?

我知道我曾经知道这一点,我知道我什至使用过这个构造,但我不记得在哪里/如何。事实证明,在网上搜索这个(“perl stdin 文件名”?不......)非常困难。

请帮忙?

4

3 回答 3

26

该变量$ARGV保存当前正在处理的文件。

$ echo hello1 > file1
$ echo hello2 > file2
$ echo hello3 > file3
$ perl -e 'while(<>){s/^/$ARGV:/; print;}' file*
file1:hello1
file2:hello2
file3:hello3
于 2012-06-21T16:15:53.223 回答
6

I/O Operators 部分perlop对此提供了非常丰富的信息。

本质上,第一次<>执行,如果它开始为空,-则添加到。@ARGV打开-具有克隆STDIN文件句柄的效果,并且变量在处理时$ARGV设置为当前元素@ARGV

这是完整的剪辑。

空文件句柄“<>”很特殊:它可以用来模拟 sed 和 awk 的行为,以及任何其他接受文件名列表的 Unix 过滤程序,对来自所有文件名的每一行输入执行相同的操作。"<>" 的输入来自标准输入,或者来自命令行上列出的每个文件。下面是它的工作原理:第一次评估“<>”时,检查@ARGV 数组,如果它为空,则 $ARGV[0] 设置为“-”,打开时会为您提供标准输入。然后将@ARGV 数组作为文件名列表进行处理。循环

   while (<>) {
       ...                     # code for each line
   }

等效于以下类似 Perl 的伪代码:

   unshift(@ARGV, '-') unless @ARGV;
   while ($ARGV = shift) {
       open(ARGV, $ARGV);
       while (<ARGV>) {
           ...         # code for each line
       }
   }

除了说起来不那么麻烦,而且实际上会起作用。它确实移动了@ARGV 数组并将当前文件名放入 $ARGV 变量中。它还在内部使用文件句柄ARGV。“<>”只是“<ARGV>”的同义词,很神奇。(上面的伪代码不起作用,因为它将“<ARGV>”视为非魔法。)

于 2015-07-08T11:44:17.100 回答
5

如果您想知道何时<>切换到新文件(例如,在我的情况下 - 我想记录新文件名和行号),那么eof() 函数文档提供了一个技巧:

# reset line numbering on each input file
while (<>) {
    next if /^\s*#/;  # skip comments
    print "$.\t$_";
} continue {
    close ARGV if eof;  # Not eof()!
}
于 2015-07-08T10:32:48.390 回答