如何使用单个文件句柄修改文件的内容

时间:2017-09-17 10:52:39

标签: perl filehandle

我正在尝试使用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

如何使用单个文件句柄修改文件内容?

2 个答案:

答案 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