问题
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:
- Lock file, scan backwards to find a position and use truncate.
- Don't print to the file directly, go through a buffer that's at least 5 lines long, and trim the buffer.
- 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