4

我在文件中有以下代码perl_script.pl

while (my $line = <>) {
    chomp $line;
   // etc. 
}. 

我用超过 1 个文件调用脚本,例如

perl perl_script.pl file1.txt file2.txt

有没有办法知道是否$line开始读取file2.txt等?

4

3 回答 3

12

$ARGV变量

读取时包含当前文件的名称<>

您可以保存名称并在每一行测试以查看它是否更改,并在更改时更新。

如果它真的只是关于获取特定文件,正如问题似乎所说的那样,那么它更容易,因为您还可以使用@ARGV包含命令行参数的 ,直接测试所需的名称。


另一种选择是使用eof(不带括号的形式!)来测试文件的结尾,这样你就会知道下一个文件将在下一次迭代中出现——所以你也需要某种标志。

对此的一种变体是在每个文件的末尾显式关闭文件句柄,以便$.为每个新文件重置,通常不会发生这种情况<>,然后$. == 1是新打开文件的第一行

while (<>) { 
    if ($. == 1) { say "new file: $ARGV" }
} 
continue { 
    close ARGV if eof;
} 
于 2020-03-03T08:28:40.723 回答
4

perldoc -f eof中记录的一个有用技巧是循环上的} continue { close ARGV if eof }成语。while (<>)这会导致$.(输入行号)在迭代的文件之间重置ARGV,这意味着它将始终1位于给定文件的第一行。

于 2020-03-03T08:49:53.563 回答
3

eof诀窍,但祝你好运,向人们解释这一点。我通常发现我也想用旧文件名做点什么。

根据您要执行的操作,您可以跟踪正在处理的文件名,以便在更改为新文件时进行识别。这样你就可以同时知道这两个名字:

use v5.10;
my %line_count;
my $current_file = $ARGV[0];
while( <> ) {
    if( $ARGV ne $current_file ) {
        say "Change of file from $current_file to $ARGV";
        $current_file = $ARGV;
        }

    $line_count{$ARGV}++
    }

use Data::Dumper;
say Dumper( \%line_count );

现在您可以看到文件何时更改,您可以使用$ARGV

Change of file from cache-filler.pl to common.pl
Change of file from common.pl to wc.pl
Change of file from wc.pl to wordpress_posts.pl
$VAR1 = {
          'cache-filler.pl' => 102,
          'common.pl' => 13,
          'wordpress_posts.pl' => 214,
          'wc.pl' => 15
        };

取决于我在做什么,我可能不会让钻石操作员完成所有工作。这让我可以更好地控制正在发生的事情以及我如何应对事情:

foreach my $arg ( @ARGV ) {
    next unless open my $fh, '<', $arg;
    while( <$fh> ) { 
        ...
        }
    }
于 2020-03-03T08:55:54.373 回答