2

ユーザー入力として合計行数を取得し、ファイルからそれらの行数を削除しています。

私はこのlearn.perl.org/faq/perlfaq5.html#How-do-I-count-the-number-of-lines-in-a-file-を見た後、以下の単純なロジックに飽きました。

論理:

  1. 行の総数を取得します
  2. ユーザーが入力した数値で減算します
  3. 行を印刷する

これが私のコードです:

#!/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;      
}

さて、私はコードにも出力にもエラーが発生していませんか?なぜ私は知らないのですか。

誰かが私にいくつかの提案をすることができますか?

4

10 に答える 10

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 $!;
于 2012-10-02T19:51:27.773 に答える
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;

これには、ファイルをメモリにロードしないという利点があります。

于 2012-10-02T19:20:28.597 に答える
4

ここでは、ストリームを通過し、最後の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
于 2012-10-02T20:00:20.940 に答える
2

INからの読み取りが終了したら、INを再度開くかseek IN, 0, 0、位置をリセットする必要があります。$.また、ゼロに再度設定する必要があります。

また、最終条件をに変更しunless $. > $printed_lineて、しきい値を超えるすべての行をスキップする必要があります。

于 2012-10-02T19:07:38.460 に答える
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;
于 2012-10-02T19:53:41.353 に答える
1

ファイルを逆に読み、最初のn行を削除するだけです。-

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

注:これにより、ファイル全体がメモリにロードされます。

于 2012-10-02T19:11:20.727 に答える
1

「もっと楽しい」答え:使用してTie::Fileください!

use strict;
use warnings;

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

$#file -= 10;
于 2012-10-02T19:21:44.773 に答える
0

のようなCで簡単for

#!/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;
于 2012-10-02T19:11:07.783 に答える
0
my $num_lines = 10;
my $qfn       = 'file.txt';

system('head', '-n', -$num_lines, '--', $qfn);
die "Error" if $?;
于 2012-10-02T19:15:06.730 に答える
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
  #
于 2012-10-28T17:19:28.817 に答える