Как я могу узнать, перешел ли бриллиантовый оператор к следующему файлу? - PullRequest
3 голосов
/ 03 марта 2020

У меня есть следующий код в файле perl_script.pl:

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

Я вызываю скрипт с более чем одним файлом, например

perl perl_script.pl file1.txt file2.txt

Есть ли способ узнать, $line начинает читать с file2.txt et c?

Ответы [ 3 ]

11 голосов
/ 03 марта 2020

Переменная $ ARGV

Содержит имя текущего файла при чтении из <>

, и вы можете сохранить имя и проверьте каждую строку, чтобы увидеть, изменилось ли оно, обновив, когда это произойдет.

Если на самом деле речь идет только о получении указанного c файла, как, кажется, говорится в вопросе, то это проще, так как вы можете также используйте @ARGV, который содержит аргументы командной строки, чтобы напрямую проверить необходимое имя.


Еще один вариант - использовать eof (форма без скобок!) для проверки конца файла, чтобы вы знали, что следующий файл будет добавлен в следующей итерации - поэтому вам также понадобится флаг какого-то рода.

Вариантом этого является явное закрытие дескриптор файла для каждого файла, так что $. получает сброс для каждого нового файла, что обычно не происходит для <>, а затем $. == 1 - это первая строка вновь открытого файла

while (<>) { 
    if ($. == 1) { say "new file: $ARGV" }
} 
continue { 
    close ARGV if eof;
} 
4 голосов
/ 03 марта 2020

Полезный прием, описанный в perldo c -f eof , - это идиома } continue { close ARGV if eof } для while (<>) l oop. Это приводит к тому, что $. (номер строки ввода) сбрасывается между файлами итерации ARGV, что означает, что он всегда будет 1 в первой строке данного файла.

3 голосов
/ 03 марта 2020

Есть трюк 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> ) { 
        ...
        }
    }
...