如何删除perl中文件的最后10行

时间:2012-10-02 19:03:45

标签: perl

我将总行数作为用户输入,然后我将从文件中删除那些数量的l ine。

我看到了这个learn.perl.org/faq/perlfaq5.html#How-do-I-count-the-number-of-lines-in-a-file-然后我厌倦了以下简单的逻辑。 / p>

逻辑:

  1. 获取总行数
  2. 按用户输入的数字
  3. 减去
  4. 打印行
  5. 这是我的代码:

    #!/usr/bin/perl -w
    use strict;
    
    open IN, "<", "Delete_line.txt"
        or die " Can not open the file $!";
    open OUT, ">", "Update_delete_line.txt" 
        or die "Can not write in the file $!";
    
    my ($total_line, $line, $number, $printed_line);
    
    print"Enter the number of line to be delete\n";
    $number = <STDIN>;
    
    while ($line = <IN>) {
    
        $total_line = $.;  # Total number of line in the file
    }
    
    $printed_line = $total_line - $number;
    
    while ($line = <IN>) {
    
        print OUT $line unless $.== $printed_line;      
    }
    

    好吧,我既没有在代码中出现任何错误,也没有任何输出错误?为什么我只是不知道。

    任何人都可以给我一些建议。

10 个答案:

答案 0 :(得分:12)

对大文件有效的Perl解决方案需要使用File::ReadBackwards

use File::ReadBackwards qw( );

my $num_lines = 10;
my $qfn = 'file.txt';

my $pos = do {
   my $fh = File::ReadBackwards->new($qfn)
      or die $!;
   $fh->readline() for 1..$num_lines;
   $fh->tell()
};

truncate($qfn, $pos)
   or die $!;
  • 这不会读取整个文件两次(与OP的方法不同)。
  • 这不会读取整个文件(与Tie::File解决方案不同)。
  • 这不会将整个文件读入内存。

答案 1 :(得分:6)

另一种方法是使用Tie::File

#!/usr/bin/env perl
use strict;
use warnings;
use Tie::File;
tie my @lines, 'Tie::File', 'myfile' or die "$!\n";
$#lines -= 10;
untie @lines;

这样做的好处是将文件加载到内存中,就像它一样。

答案 2 :(得分:4)

这是一个通过流并打印除 n 之前的所有 n 行以外的所有行的解决方案: n 是命令行参数:

#!/usr/bin/perl

my @cache;
my $n = shift @ARGV;

while(<>) {
    push @cache, $_;
    print shift @cache if @cache > $n;
}

或单行版本:

perl -ne'BEGIN{$n=shift@ARGV}push@c,$_;print shift@c if@c>$n' NUMBER

答案 3 :(得分:2)

完成从IN读取后,您必须重新打开它或seek IN, 0, 0重置其位置。您还必须再次将$.设置为零。

此外,最终条件应更改为unless $. > $printed_line,以便跳过超过阈值的所有行。

答案 4 :(得分:1)

只需反向读取文件并删除前n行: -

open my $filehandle, "<", "info.txt";
my @file = <$filehandle>;
splice(@file, -10);
print @file;

注意:这会将整个文件加载到内存中。

答案 5 :(得分:1)

“更有趣”的答案:使用Tie::File

use strict;
use warnings;

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

$#file -= 10;

答案 6 :(得分:1)

您可以缓冲最后10行,然后不打印剩下的10行。

use English qw<$INPLACE_EDIT>;

{   local @ARGV         = $name_of_file_to_edit;
    local $INPLACE_EDIT = '.bak';
    my @buffer;
    for ( 1..$num_lines_to_trim ) { 
        push @buffer, <>;
    }

    while ( <> ) { 
        print shift @buffer;
        push @buffer, $_;
    }
}

您也可以使用File::Slurp::edit_file_lines执行此操作:

my @buffer;
my $limit_reached = 0;
edit_file_lines {  
    push @buffer, $_;
    return ( $limit_reached ||= @buffer > $num_lines_to_trim ) ? shift @buffer
         :                                                       ''
         ;
} $name_of_file;

答案 7 :(得分:0)

使用像for

这样的C很容易
#!/usr/bin/perl -w
use strict;

open(my $in,"<","Delete_line.txt") or die "Can not open the file $!";
open(my $out,">","Update_delete_line.txt") or die"Can not write in the file $!";

print"Enter the number of lines to be delete\n";
my $number=<STDIN>;

my @file = <$in>;

for (my $i = 0; $i < $#file - $number + 1; $i++) {
    print $out $file[$i];
}

close $in;
close $out;

答案 8 :(得分:0)

my $num_lines = 10;
my $qfn       = 'file.txt';

system('head', '-n', -$num_lines, '--', $qfn);
die "Error" if $?;

答案 9 :(得分:0)

  #
  # Reads a file trims the top and the bottom of by passed num of lines
  # and return the string 
  # stolen from : http://stackoverflow.com/a/9330343/65706
  # usage :       
  # my $StrCatFile = $objFileHandler->ReadFileReturnTrimmedStrAtTopBottom ( 
  #       $FileToCat , $NumOfRowsToRemoveAtTop , $NumOfRowsToRemoveAtBottom) ; 
  sub ReadFileReturnTrimmedStrAtTopBottom {

     my $self = shift ; 
     my $file = shift ; 
     my $NumOfLinesToRemoveAtTop = shift ; 
     my $NumOfLinesToRemoveAtBottom = shift ; 

     my @cache ; 
     my $StrTmp = () ; 
     my $StrReturn = () ; 
     my $fh = () ; 

     open($fh, "<", "$file") or cluck (   "can't open file : $file for reading: $!" ) ;
     my $counter = 0;
     while (<$fh>) {
         if ($. >= $NumOfLinesToRemoveAtTop + 1) {
             $StrTmp .= $_ ;
         }
     } 
     close $fh;

     my $sh = () ; 
     open( $sh, "<", \$StrTmp) or cluck(   "can't open string : $StrTmp for reading: $!" ) ;
     while(<$sh>) {
         push ( @cache, $_  ) ;
         $StrReturn .= shift @cache if @cache > $NumOfLinesToRemoveAtBottom;
     }
     close $sh ; 
     return $StrReturn ; 
  } 
  #eof ReadFileReturnTrimmedStrAtTopBottom
  #