Perl 提供了这个非常好的特性:
while ( <> )
{
# do something
}
...这允许使用脚本script.pl <filename>
以及cat <filename> | script.pl
.
现在,有没有办法确定脚本是否以前一种方式被调用,如果是,文件名是什么?
我知道我曾经知道这一点,我知道我什至使用过这个构造,但我不记得在哪里/如何。事实证明,在网上搜索这个(“perl stdin 文件名”?不......)非常困难。
请帮忙?
Perl 提供了这个非常好的特性:
while ( <> )
{
# do something
}
...这允许使用脚本script.pl <filename>
以及cat <filename> | script.pl
.
现在,有没有办法确定脚本是否以前一种方式被调用,如果是,文件名是什么?
我知道我曾经知道这一点,我知道我什至使用过这个构造,但我不记得在哪里/如何。事实证明,在网上搜索这个(“perl stdin 文件名”?不......)非常困难。
请帮忙?
该变量$ARGV
保存当前正在处理的文件。
$ echo hello1 > file1
$ echo hello2 > file2
$ echo hello3 > file3
$ perl -e 'while(<>){s/^/$ARGV:/; print;}' file*
file1:hello1
file2:hello2
file3:hello3
的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>”视为非魔法。)
如果您想知道何时<>
切换到新文件(例如,在我的情况下 - 我想记录新文件名和行号),那么eof() 函数文档提供了一个技巧:
# reset line numbering on each input file
while (<>) {
next if /^\s*#/; # skip comments
print "$.\t$_";
} continue {
close ARGV if eof; # Not eof()!
}