如何在perl中删除文件的最后10行
我将总行数作为用户输入,然后从文件中删除这些行数 我看到这个learn.perl.org/faq/perlfaq5.html#How-do-I-count-the-number-of-line-in-a-file-然后我厌倦了下面的简单逻辑 逻辑:如何在perl中删除文件的最后10行,perl,Perl,我将总行数作为用户输入,然后从文件中删除这些行数 我看到这个learn.perl.org/faq/perlfaq5.html#How-do-I-count-the-number-of-line-in-a-file-然后我厌倦了下面的简单逻辑 逻辑: 获取行的总数 减去用户输入的数字 打印行 这是我的代码: #!/usr/bin/perl -w use strict; open IN, "<", "Delete_line.txt" or die " Can not open the
#!/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;
}
#/usr/bin/perl-w
严格使用;
在“,”更新\删除\行.txt”中打开
或死“无法写入文件$!”;
我的($total\u line,$line,$number,$printed\u line);
打印“输入要删除的行数\n”;
$number=;
而($line=){
$total_line=$。;#文件中的行总数
}
$printed_line=$total_line-$number;
而($line=){
打印出$行,除非$.==$打印行;
}
嗯,我既没有收到任何代码错误,也没有收到任何输出?为什么我不知道
谁能给我一些建议吗 从中读取完毕后,您必须重新打开它或
在0,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;
#/usr/bin/perl-w
严格使用;
打开(my$in,“,”Update_delete_line.txt“)或死“无法写入文件$!”;
打印“输入要删除的行数\n”;
我的$number=;
my@file=;
对于(我的$i=0;$i<$#文件-$number+1;$i++){
打印$out$file[$i];
}
以美元收盘;
收尾美元;
只需反向读取文件并删除前n行:-
open my $filehandle, "<", "info.txt";
my @file = <$filehandle>;
splice(@file, -10);
print @file;
打开我的$filehandle,”另一种方法是使用
这样做的好处是,不会像加载文件一样将文件加载到内存中。更有趣的答案是:使用
对于大型文件高效的Perl解决方案需要使用
- 这不会读取整个文件两次(与OP的方法不同)
- 这不会读取整个文件(与解决方案不同)
- 这不会将整个文件读入内存
您可以缓冲最后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, $_;
}
}
这里是一个通过流并打印除最后n行以外的所有行的解决方案,其中n是命令行参数:
#!/usr/bin/perl
my @cache;
my $n = shift @ARGV;
while(<>) {
push @cache, $_;
print shift @cache if @cache > $n;
}
#
#读取文件修剪通过的行数的顶部和底部
#然后返回字符串
#被盗自:http://stackoverflow.com/a/9330343/65706
#用法:
#my$StrCatFile=$objFileHandler->ReadFileReturnTrimmedStrAtTopBottom(
#$FileToCat、$numorwstoremoveattop、$numorwstoremoveattown);
子读取文件返回TrimmedStratTopBottom{
我的$self=shift;
我的$file=shift;
我的$NumOfLinesToRemoveAtTop=shift;
我的$NumOfLinesToRemoveAtBottom=shift;
我的@cache;
我的$StrTmp=();
我的$StrReturn=();
我的$fh=();
open($fh,“难道你不能反向读取文件吗?”并删除前n行吗?全局文件句柄被本地文件句柄取代,这更安全&这是一种最佳做法。请参阅,这也会向后打印文件。因此,你仍然在向后打印文件(最后10行除外)@mob..O.O..Nice catch mob..那么这可能只用于删除行..@choroba.我尝试了seek函数,我的意思是我添加了seek(IN,0,0)我将$.=0;现在输出即将到来,但它没有删除最后10行,我的意思是它正在按原样打印整行。注意:这将读取整个文件,并为内存中的每一行创建索引。我的解决方案两者都没有。注意:这将读取整个文件,并为内存中的每一行创建索引。我的解决方案两者都没有。+1,这是最好的回答(除非需要就地编辑)。“这不会读取整个文件(与Tie::file solutions不同)”=>我读到“Tie::file solutions是最有效的解决方案,至少对于大型文件而言,因为它不必读取整个文件以找到最后一行,也不会将整个文件读入内存”,请参阅@Georg,Tie::File很少是最有效的解决方案。由于其所有开销,它最多只能与专用解决方案(如File::ReadBackwards)一样快。但这里不是这样。建议的解决方案使用$#行
,这必然会导致读取整个文件。我希望弹出(@lines)对于1..10;
或删除($lines[-1]),对于1..10;
的速度几乎与F::RB解决方案一样快,但我使用strace
确认他们也读取了整个文件(即使他们可以使用与F::RB相同的方法)@Georg,这还不算内存使用率。Tie::File保存了它遇到的每一行的位置索引。delete($lines[-1])
在一个包含64字节行的8MiB文件上,导致Tie::File为这些偏移量使用了刚刚超过4MiB的内存!!!(它们不属于可以控制大小的缓存和缓冲区。)@Georg,链接的文档是完全错误的。Tie::File与前面的代码段做的事情完全相同,但有很多额外的CPU和内存开销。@Georg,Gah,如果您的平均行很短(例如,与源代码一样),那么Tie::File实际上可以为其偏移量使用比整个文件更多的内存!!!
use strict;
use warnings;
use Tie::File;
tie my @file, 'Tie::File', 'filename' or die "$!";
$#file -= 10;
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 $!;
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, $_;
}
}
my @buffer;
my $limit_reached = 0;
edit_file_lines {
push @buffer, $_;
return ( $limit_reached ||= @buffer > $num_lines_to_trim ) ? shift @buffer
: ''
;
} $name_of_file;
#!/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
#
# 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
#