如何删除文件的最后5行

时间:2012-02-17 14:15:46

标签: perl file printing lines

我有几个命令使用perl将文本打印到文件。在这些print命令期间,我有一个if语句,如果语句为真,它应该删除我当前正在写入的文件的最后5行。要删除的行数始终为5。

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

6 个答案:

答案 0 :(得分:4)

您可以使用Tie::File

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

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

您可以在打印时使用相同的数组,但请改用push

push @array, "line of text";

答案 1 :(得分:3)

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

答案 2 :(得分:1)

只有我能想到的明显方法:

  1. 锁定文件scan backwards以查找位置并使用 truncate
  2. 不要直接打印到文件,请通过缓冲区 这至少有5行,并修剪缓冲区。
  3. 打印标记,表示“忽略最后五行”。 在使用缓冲区读取它们之前处理所有文件,如#2
  4. 所有这些都非常繁琐,但这是我害怕的平面文件的本质。

    HTH

答案 3 :(得分:1)

作为替代方案,打印除最后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: $!";

答案 4 :(得分:1)

对于大型文件,

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是最慢的,并且使用大量内存。避免这种解决方案。

答案 5 :(得分:0)

你可以尝试这样的事情:

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]";
}