Perl:使用<>时如何获取文件名构造?

时间:2012-06-21 16:13:45

标签: perl

Perl提供了这个非常好的功能:

while ( <> )
{
    # do something
}

...允许将脚本用作script.pl <filename>以及cat <filename> | script.pl

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

我知道我曾经知道这一次,我知道我甚至使用了这个结构,但我不记得在哪里/如何。事实证明很难搜索'net for this(“perl stdin filename”?不......)。

请帮帮忙?

3 个答案:

答案 0 :(得分:22)

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

$ echo hello1 > file1
$ echo hello2 > file2
$ echo hello3 > file3
$ perl -e 'while(<>){s/^/$ARGV:/; print;}' file*
file1:hello1
file2:hello2
file3:hello3

答案 1 :(得分:4)

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

# reset line numbering on each input file
while (<>) {
    next if /^\s*#/;  # skip comments
    print "$.\t$_";
} continue {
    close ARGV if eof;  # Not eof()!
}

答案 2 :(得分:4)

I/O Operators section of perlop对此非常有用。

基本上,第一次执行<>时,-会在@ARGV开始为空时添加到-。打开STDIN可以克隆$ARGV文件句柄,变量@ARGV会在处理时设置为 while (<>) { ... # code for each line } 的当前元素。

这是完整的剪辑。

  

null文件句柄&#34;&lt;&gt;&#34;很特别:它可以用来模仿      sed和awk的行为,以及任何其他需要的Unix过滤器程序      文件名列表,对所有输入的每一行都做同样的事情      他们。输入来自&#34;&lt;&gt;&#34;来自标准输入,或来自每个      命令行中列出的文件。以下是它的工作原理:第一次      &#34;&LT;&GT;&#34;进行评估,检查@ARGV数组,如果为空,      $ ARGV [0]设置为&#34; - &#34;,打开时为您提供标准输入。该      然后将@ARGV数组作为文件名列表处理。循环

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

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

class User < ActiveRecord::Base
  has_many :posts
end

class Post < ActiveRecord::Base
  belongs_to: user
end
     

除了它说起来不那么麻烦,并且实际上会起作用。它      确实会移动@ARGV数组并将当前文件名放入      $ ARGV变量。它还在内部使用文件句柄 ARGV 。 &#34;&LT;&GT;&#34;只是      &#34;&lt; ARGV&gt;&#34;的同义词,这是神奇的。 (上面的伪代码不是      工作,因为它对待&#34;&lt; ARGV&gt;&#34;非魔法。)