我正在尝试使用Perl修改文件的内容。
以下脚本可以正常工作。
#!/usr/bin/perl
use strict;
use warnings;
open(FH,"test.txt") || die "not able to open test.txt $!";
open(FH2,">","test_new.txt")|| die "not able to opne test_new.txt $!";
while(my $line = <FH>)
{
$line =~ s/perl/python/i;
print FH2 $line;
}
close(FH);
close(FH2);
test.txt
的内容:
im learning perl
im in File handlers chapter
test_new.txt
中的输出:
im learning python
im in File handlers chapter
如果我尝试使用相同的文件句柄来修改文件内容,那么我没有得到预期的输出。以下是尝试执行此操作的脚本:
#!/usr/bin/perl
use strict;
use warnings;
open(FH,"+<","test.txt") || die "not able to open test.txt $!";
while(my $line = <FH>)
{
$line =~ s/perl/python/i;
print FH $line;
}
close(FH);
test.txt
中的输出错误:
im learning perl
im learning python
chapter
chapter
如何使用单个文件句柄修改文件内容?
答案 0 :(得分:2)
您无法从文件中删除(最后除外) 您不能将字符插入文件中(最后除外)。
您可以替换文件中的字符 您可以附加到文件 您可以缩短文件 而已。
你想象你可以简单地用文件中的“Python”替换“Perl”。那些长度不一样,所以需要在文件中插入字符,你不能这样做。
通过将文件的其余部分加载到内存中并将其写回两个字符,可以有效地将字符插入到文件中。但对于非常大的文件,这样做会变得棘手。它也非常慢,因为每次要插入字符时,最终都会复制文件的一部分(可能非常大)。
就地修改的另一个问题是您无法从错误中恢复。如果发生某些事情,您将留下不完整或损坏的文件。
如果文件很小,如果出现问题就可以丢失数据,最简单的方法是将整个文件加载到内存中。
open(my $fh, '<+', $qfn)
or die("Can't open \"$qfn\": $!\n");
my $file = do { local $/; <$fh> };
$file =~ s/Perl/Python/g;
seek($fh, 0, SEEK_SET)
or die $!;
print($fh $file)
or die $!;
truncate($fh)
or die $!;
更安全的方法是将数据写入新文件,然后在完成后重命名该文件。
my $new_qfn = $qfn . ".tmp";
open(my $fh_in, '<', $qfn)
or die("Can't open \"$qfn\": $!\n");
open(my $fh_out, '<', $new_qfn)
or die("Can't create \"$new_qfn\": $!\n");
while (<$fh_in>) {
s/Perl/Python/g;
print($fh_out $_);
}
close($fh_in);
close($fh_out);
rename($qfn_new, $qfn)
or die $!;
这种方法的缺点是它可能会更改文件的权限,而硬链接将指向旧内容而不是新文件。您还需要创建文件的权限。
答案 1 :(得分:0)
@Сухой27回答
这是perl onliner愉快使用的典型情况。
perl -i -pe的/ perl / python / i'
perl
采用以下选项
-p
:逐行循环播放(每行分配到$_
并在评估$_
后打印)-e
:评估上述循环中的代码块(正则表达式将$_
作为默认操作数)-i
:在plcae文件编辑中(如果你传递-i的参数,perl保留带有该扩展名的原始文件)如果你在脚本下面运行
perl -i.bak -pe的/ perl / python / i'test.txt
您将被修改test.txt
im learning python
im in File handlers chapter
并获取test.txt.bak
im learning perl
im in File handlers chapter