Как сбросить $.?

Я знаю, что $. показывает номер строки, когда $/ установлено на "\n".

Я хотел эмулировать команду Unix tail в Perl и распечатать последние 10 строк из файла, но $. не сработало. Если файл содержит 14 строк, он начинается с 15 в следующем цикле.

#!/usr/bin/perl
use strict;
use warnings;

my $i;

open my $fh, '<', $ARGV[0] or die "unable to open file $ARGV[0] :$! \n";
do { local $.; $i = $. } while (<$fh>);
seek $fh, 0, 0;

if ($i > 10) {
    $i = $i - 10;
    print "$i \n";
    while (<$fh>) {

        #local $.;# tried doesn't work
        #undef $.; #tried doesn't work

        print "$. $_" if ($. > $i);
    }
}
else {
    print "$_" while (<$fh>);
}

close($fh);

Я хочу сбросить $., чтобы его можно было использовать в следующем цикле.


person Arunesh Singh    schedule 10.06.2015    source источник
comment
Не ответ на ваш вопрос, а альтернативное решение вашей первоначальной проблемы. Чтобы напечатать последние десять строк, вы можете использовать это: perl -nle 'push @tail, $_; shift @tail if @tail > 10; END {print foreach (@tail)}' input.txt   -  person Dmitry Egorov    schedule 10.06.2015
comment
Это обсуждение может вам помочь: stackoverflow.com/questions/6036244/   -  person chipou    schedule 10.06.2015
comment
Вот еще одна реализация tail в Perl 5: metacpan.org/source/ BDFOY/PerlPowerTools-1.006/bin/tail#L142   -  person dolmen    schedule 10.06.2015


Ответы (2)


Использование local с $. делает что-то другое, чем вы думаете:

Локализация $. не будет локализовать количество строк дескриптора файла. Вместо этого он локализует представление Perl о том, какой дескриптор файла $. в настоящее время является псевдонимом.

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

1 while <$fh>;
my $i = $.;
seek $fh, $. = 0, 0;
person choroba    schedule 10.06.2015
comment
но мы можем использовать local для $/, чтобы установить его значение, но для $. почему мы не можем использовать местный? - person Arunesh Singh; 10.06.2015
comment
@ArruneshSingh: см. $. в perlvar. Цитата оттуда. - person choroba; 10.06.2015

Вы должны повторно открыть дескриптор файла. В противном случае, как вы обнаружили, номер строки просто продолжает увеличиваться.

#!/usr/bin/perl
use strict;
use warnings;

my ($filename) = @ARGV;

my $num_lines;
open my $fh, '<', $filename or die qq{Unable to open file "$filename" for input: $!\n};
++$num_lines while <$fh>;

open $fh, '<', $filename or die qq{Unable to open file "$filename" for input: $!\n};

print "$num_lines lines\n";
while ( <$fh> ) {
    print "$. $_" if $. > $num_lines - 10;
}

Вот более аккуратный способ

#!/usr/bin/perl
use strict;
use warnings;

my ($filename) = @ARGV;

my @lines;
open my $fh, '<', $filename or die qq{Unable to open file "$filename" for input: $!\n};

while ( <$fh> ) {
  push @lines, $_;
  shift @lines while @lines > 10;
}

print @lines;
person Borodin    schedule 10.06.2015