Perl提供了这个非常好的功能:
while ( <> )
{
# do something
}
Run Code Online (Sandbox Code Playgroud)
...允许脚本script.pl <filename>
和...一样使用cat <filename> | script.pl
.
现在,有没有办法确定脚本是否以前一种方式被调用,如果是,文件名是什么?
我知道我知道这一次,我知道我甚至使用了这个结构,但我不记得在哪里/如何.事实证明很难搜索'net for this("perl stdin filename"?不......).
请帮忙?
Igo*_*bin 23
该变量$ARGV
保存正在处理的当前文件.
$ echo hello1 > file1
$ echo hello2 > file2
$ echo hello3 > file3
$ perl -e 'while(<>){s/^/$ARGV:/; print;}' file*
file1:hello1
file2:hello2
file3:hello3
Run Code Online (Sandbox Code Playgroud)
的I/O 操作员部分perlop
对此提供了非常丰富的信息。
本质上,第一次<>
执行时,如果它开始为空,-
则添加到@ARGV
。Opening-
具有克隆STDIN
文件句柄的效果,并且该变量在处理时$ARGV
设置为 的当前元素@ARGV
。
这是完整的剪辑。
空文件句柄“<>”是特殊的:它可以用来模拟 sed 和 awk 的行为,以及任何其他接受文件名列表的 Unix 过滤程序,对来自所有文件名的每一行输入执行相同的操作。"<>" 的输入来自标准输入,或来自命令行中列出的每个文件。这是它的工作原理:第一次计算“<>”时,检查@ARGV 数组,如果它为空,则 $ARGV[0] 设置为“-”,打开时为您提供标准输入。然后将@ARGV 数组作为文件名列表进行处理。循环
Run Code Online (Sandbox Code Playgroud)while (<>) { ... # code for each line }
等价于以下类似 Perl 的伪代码:
Run Code Online (Sandbox Code Playgroud)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()!
}
Run Code Online (Sandbox Code Playgroud)