3

我最终让我的脚本将我想要进行的新更改附加到文件末尾而不是实际文件中。

open (INCONFIG, "+<$text") or die $!;
@config = <INCONFIG>;
foreach(@config)
{
    if ( $_ =~ m/$checker/ )
    {
        $_ = $somethingnew;
    }
print INCONFIG $_;
}
close INCONFIG or die;

最终我想再次重写整个文本,但如果它与搜索条件匹配,则修改某些字符串。但到目前为止,它只将整个文件的另一个副本(带有更改)附加到旧文件的底部。

我知道我可以关闭该文件,并使用另一个写入文件-句柄并解析它。但希望能够了解我做错了什么,以及如何解决它。

4

4 回答 4

1

据我了解open,对文本文件使用读/写访问权限并不是一个好主意。毕竟文件只是一个字节流:用不同长度的东西更新文件的一部分是令人头疼的东西;-)

这是我的方法:尝试模拟-iperl 的“就地”开关。所以本质上我们写入一个备份文件,稍后我们将对其进行重命名。(在 *nix 系统上,打开文件句柄有一些魔力可以保持已删除的文件可用,因此我们不必创建新文件。不管怎样,让我们​​来做吧。)

my $filename = ...;
my $tempfile = "$filename.tmp";
open my $inFile,  '<', $filename or die $!;
open my $outFile, '>', $tempfile or die $!;

while (my $line = <$inFile>) {
    $line = doWeirdSubstitutions($line);
    print $outFile $line;
}

close $inFile  or die $!;
close $outFile or die $!;

rename $tempfile, $filename
  or die "rename failed: $!"; # will break under weird circumstances.

# delete temp file
unlink $tempfile or die $!;

未经测试,但显而易见的代码。这对您的问题有帮助吗?

于 2012-07-23T12:14:36.150 回答
0

正如其他人指出的那样,有更好的方法:)

但是如果你真的想用 读写+<,你应该记住,在读取文件之后,你就在文件的末尾……这说明你的输出是附加在原始内容之后的。

您需要做的是将文件指针重置为文件的开头,使用seek

seek(INCONFIG ,0,0);

然后开始写...

于 2012-07-23T14:18:29.580 回答
0

您的问题是对 <+ "open for update" 的作用有误解。Perl 教程的 Mixing Reads and Writes对此进行了讨论。

您真正想要做的是将旧文件复制到新文件,然后在事后重命名。这在daxim提到的 perlfaq5 中有讨论。此外,还有专门用于安全执行此操作的完整模块,例如File::AtomicWrite。这些有助于解决您的程序中止并给您留下一个损坏的文件的问题。

于 2012-07-23T12:12:16.910 回答
0

perlopentut这是关于混合读写的

事实上,当涉及到更新文件时,除非您正在处理上述 WTMP 案例中的二进制文件,否则您可能不想使用这种方法进行更新。相反,Perl 的 -i 标志来拯救。

另一种方法是使用Tie::File模块。代码简化为:

tie my @config, 'Tie::File', $text or die $!;

s/$checker/$somethingnew/g for @config;

请记住在修改程序之前备份文件,直到您调试了程序。

于 2012-07-23T15:02:59.337 回答