我有巨大的文本文件,并第一五行的记载如下:
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
我不希望将整个文件读入一个数组,我也不希望使用领带::文件。 是否有可能使用seek和tell达到我的要求? 一个解决方案将是非常有益的。
文件是一个字节序列。 我们可以更换 (重写)其中的一部分,但我们会怎么删除 ? 一旦文件被写入其字节不能序列的“拉出”或以任何方式“空白”。 (在该文件的末尾的那些可被驳回,根据需要通过截断文件)。
内容的其余部分必须移动“上升”,从而使接下来要除去覆盖它的文本。 我们不得不重新改写文件的其余部分。 在实践中,往往是简单得多重写整个文件。
作为一个非常简单的例子
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: $!";
此写入输入文件的每行到输出文件中,除非线的给定模式的匹配。 然后该文件被重命名,取代了原有的(什么不涉及数据复制)。 见在perlfaq5这个话题 。
因为我们真正使用的临时文件,我建议的核心模块文件::温度为。
这可以由更有效,但更为复杂,通过在更新打开'+<'
模式,以便覆盖只有文件的一部分。 您迭代,直到与模式,记录(行tell
),它的位置和线路长度,然后将所有剩余的行复制到内存中。 然后, seek
回该线的位置减去长度,并转储文件的复制休息,覆盖线和所有它后面。
请注意,现在对于文件的其余部分中的数据被复制两次 ,虽然一个副本在内存中。 去这个麻烦可能是有意义的,如果要删除的行远了非常大的文件。 如果有更多的线路来消除这种混乱得到。
写出一个新的文件,并复制它在原来的改变文件的inode编号。 这可能是一些工具或程序出了问题,如果是,则可以改为通过更新或者原
之后完成了复制。 这需要一定的照顾和第一种方式可能是一般更安全。
如果文件不是巨大的新的“文件”,可以在内存中“写”,作为一个数组或一个字符串。
使用sed
从在Perl Linux命令行命令:
my $return = `sed -i '3d' text.txt`;
其中,“3D”是指删除第3行。
这要看是有用perlrun
,看看自己如何perl的修改文件“就地”。
鉴于:
$ cat text.txt
This is fist line
This is second line
This is third line
This is fourth line
This is fifth line
你显然已经“修改就地”,sed的一样,通过使用-i
和-p
开关来调用Perl的:
$ perl -i -pe 's/This is third line\s*//' text.txt
$ cat text.txt
This is fist line
This is second line
This is fourth line
This is fifth line
但是,如果你请教Perl的菜谱食谱7.9(或看perlrun ),你会看到这一点:
$ perl -i -pe 's/This is third line\s*//' text.txt
相当于:
while (<>) {
if ($ARGV ne $oldargv) { # are we at the next file?
rename($ARGV, $ARGV . '.bak');
open(ARGVOUT, ">$ARGV"); # plus error check
select(ARGVOUT);
$oldargv = $ARGV;
}
s/This is third line\s*//;
}
continue{
print;
}
select (STDOUT); # restore default output