How to delete the last 5 lines of a file

北城余情 提交于 2019-12-23 06:45:15

问题


I have several commands printing text to a file using perl. During these print commands I have an if statement which should delete the last 5 lines of the file I am currently writing to if the statement is true. The number of lines to delete will always be 5.

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

回答1:


You can use Tie::File:

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

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

You can use the same array when printing, but use push instead:

push @array, "line of text";



回答2:


$ tac file | perl -ne 'print unless 1 .. 5' | tac > file.tailchopped



回答3:


Only obvious ways I can think of:

  1. Lock file, scan backwards to find a position and use truncate.
  2. Don't print to the file directly, go through a buffer that's at least 5 lines long, and trim the buffer.
  3. Print a marker that means "ignore the last five lines". Process all your files before reading them with a buffer as in #2

All are pretty fiddly, but that's the nature of flat files I'm afraid.

HTH




回答4:


As an alternative, print the whole file except last 5 lines:

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: $!";



回答5:


File::ReadBackwards+truncate is the fastest for large files, and probably as fast as anything else for short files.

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 is the slowest, and uses a large amount of memory. Avoid that solution.




回答6:


you can try something like this:

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

or even shortened:

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


来源:https://stackoverflow.com/questions/9329799/how-to-delete-the-last-5-lines-of-a-file

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!