从Perl中的大文件中删除一行
我有一个巨大的文本文件,前五行如下:
This is fist line This is second line This is third line This is fourth line This is fifth line 现在,我想在该文件的第三行的随机位置写一些东西,它将用我正在编写的新字符串替换该行中的字符.我能用以下代码实现这一点: use strict; use warnings; my @pos = (0); open my $fh,"+<","text.txt"; while(<$fh) { push @pos,tell($fh); } seek $fh,$pos[2]+1,0; print $fh "HELLO"; close($fh); 但是,我无法用同样的方法弄清楚如何从该文件中删除整个第三行,以便文本如下所示: This is fist line This is second line This is fourth line This is fifth line 我不想将整个文件读入数组,也不想使用Tie :: File.是否有可能使用搜索和告诉来实现我的要求?解决方案将非常有用. 解决方法
文件是一个字节序列.我们可以替换(覆盖)其中的一些,但我们如何删除它们?一旦文件被写入,其字节就不能被“拉出”序列或以任何方式“消隐”. (根据需要截断文件,可以解除文件末尾的那些.)
其余内容必须向上移动,以便删除的文本后面的内容将覆盖它.我们必须重写文件的其余部分.在实践中,重写整个文件通常要简单得多. 作为一个非常基本的例子 use warnings 'all'; use strict; use File::Copy qw(move); my $file_in = '...'; my $file_out = '...'; # best use `File::Temp` open my $fh_in,'<',$file_in or die "Can't open $file_in: $!"; open my $fh_out,'>',$file_out or die "Can't open $file_out: $!"; # Remove a line with $pattern my $pattern = qr/this line goes/; while (<$fh_in>) { print $fh_out $_ unless /$pattern/; } close $fh_in; close $fh_out; # Rename the new fie into the original one,thus replacing it move ($file_out,$file_in) or die "Can't move $file_out to $file_in: $!"; 这会将输入文件的每一行写入输出文件,除非一行与给定的模式匹配.然后重命名该文件,替换原始文件(不涉及数据副本).见this topic in perlfaq5. 由于我们确实使用临时文件,因此我建议使用核心模块File::Temp. 通过打开更新’<'可以提高效率,但要复杂得多.模式,以便只覆盖文件的一部分.迭代直到带有模式的行,记录(告诉)它的位置和行长度,然后复制内存中的所有剩余行.然后回到该行的减去长度的位置,并转储复制的文件的其余部分,覆盖该行及其后面的所有内容. 请注意,现在文件其余部分的数据被复制两次,尽管一个副本在内存中.如果要删除的行远远超过非常大的文件,那么遇到这种麻烦可能有意义.如果有更多行要删除,这会变得更加混乱. 写出新文件并将其复制到原始文件会更改文件的inode编号.对于某些工具或程序而言,这可能是一个问题,如果是,您可以通过其中任何一个更新原始文件 truncate $fh,tell($fh); 复制完成后.这需要一些小心,第一种方式通常可能更安全. 如果文件不是很大,则新的“文件”可以作为数组或字符串“写入”内存中. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |