Как удалить последние 5 строк файла - PullRequest
0 голосов
/ 17 февраля 2012

У меня есть несколько команд, печатающих текст в файл с использованием perl. Во время этих команд print у меня есть оператор if, который должен удалить последние 5 строк файла, в который я сейчас пишу, если этот оператор верен. Количество удаляемых строк всегда будет 5.

if ($exists == 0) {
  print(OUTPUT ???) # this should remove the last 5 lines
}

Ответы [ 6 ]

4 голосов
/ 17 февраля 2012

Вы можете использовать Tie :: File :

use Tie::File;
tie my @array, 'Tie::File', filename or die $!;

if ($exists == 0) {
    $#array -= 5;
}

Вы можете использовать тот же массив при печати, но вместо него используйте push:

push @array, "line of text";
3 голосов
/ 17 февраля 2012
$ tac file | perl -ne 'print unless 1 .. 5' | tac > file.tailchopped
1 голос
/ 18 февраля 2012

File :: ReadBackwards + truncate - самый быстрый для больших файлов и, вероятно, такой же быстрый, как и все остальные для коротких файлов.

use File::ReadBackwards qw( );

my $bfh = File::ReadBackwards->new($qfn)
   or die("Can't read \"$qfn\": $!\n");

$bfh->readline() or last for 1..5;

my $fh = $bfh->get_handle();
truncate($qfn, tell($fh))
   or die $!;

Tie :: File является самым медленным и использует большой объем памяти. Избегайте этого решения.

1 голос
/ 17 февраля 2012

В качестве альтернативы выведите весь файл, кроме последних 5 строк:

open($fh, "<", $filename) or die "can't open $filename for reading: $!";
open($fh_new, ">", "$filename.new") or die "can't open $filename.new: $!";
my $index = 0; # So we can loop over the buffer
my @buffer;
my $counter = 0;
while (<$fh>) {
    if ($counter++ >= 5) {
        print $fh_new $buffer[$index];
    }
    $buffer[$index++] = $_;
    $index = 0 if 5 == $index;
}
close $fh;
close $fh_new;
use File::Copy;
move("$filename.new", $filename) or die "Can not copy $filename.new to $filename: $!";
1 голос
/ 17 февраля 2012

Только очевидные способы, которыми я могу придумать:

  1. Файл блокировки, сканирование в обратном направлении для поиска позиции и использования усечение .
  2. Не печатать в файл напрямую, пройти через буфер это по крайней мере 5 строк, и обрезать буфер.
  3. Распечатать маркер, который означает «игнорировать последние пять строк». Обработайте все ваши файлы, прежде чем читать их с помощью буфера, как в # 2

Все довольно неудобно, но я боюсь, что это характер плоских файлов.

НТН

0 голосов
/ 18 февраля 2012

вы можете попробовать что-то вроде этого:

open FILE, "<", 'filename';
if ($exists == 0){
 @lines = <FILE>;
 $newLastLine = $#lines - 5;   
 @print = @lines[0 .. $newLastLine];
 print "@print";
}

или даже сократить:

open FILE, "<", 'filename';
@lines = <FILE>;
if ($exists == 0){
 print "@lines[0 .. $#lines-5]";
}
...