需要Perl就地编辑不在命令行上的文件

| 我有一个内部配置了多个文件名的程序。该程序将编辑与数据库帐户关联的一堆配置文件,然后更改该数据库帐户的数据库密码。 配置文件列表通过内部列表与数据库帐户的名称关联。当我处理这些文件时,程序中具有以下循环:
BEGIN { $^I = \'.oldPW\'; }  # Enable in-place editing
...
foreach (@{$Services{$request}{\'files\'}})
{
    my $filename = $Services{$request}{\'configDir\'} . \'/\' . $_;
    print \"Processing ${filename}\\n\";
    open CONFIGFILE, \'+<\', $filename or warn $!;
    while (<CONFIGFILE>)
    {
        s/$oldPass/$newPass/;
        print;
    }
    close CONFIGFILE;
}
问题是,这会将修改后的输出写入STDOUT,而不是CONFIGFILE。如何获得此内容以进行实际编辑?将$ ^ I移入循环?打印CONFIGFILE?我很沮丧。 > 更新:我在PerlMonks上找到了想要的东西。您可以在循环内使用本地ARGV以常规Perl方式进行就地编辑。上面的循环现在看起来像:
foreach (@{$Services{$request}{\'files\'}})
{
    my $filename = $Services{$request}{\'configDir\'} . \'/\' . $_;
    print \"Processing ${filename}\\n\";
    {
        local @ARGV = ( $filename);
        while (<>)
        {
            s/$oldPass/$newPass/;
            print;
        }
    }
}
如果不是一开始就添加configDir,我可以将整个列表扔到本地@ARGV中,但这足够有效。 感谢您对
Tie::File
的有益建议。如果结束,我可能会那样做。我正在编辑的配置文件的长度从不超过几KB,因此Tie不会使用过多的内存。     
已邀请:
versions3ѭ的最新版本提供了便捷的功能
edit_file
和convenient5ѭ。您的代码的内部看起来像:
use File::Slurp qw(edit_file);
edit_file { s/$oldPass/$newPass/g } $filename;
    
$^I
变量仅使用空的
<>
构造对保存在held8ѭ中的文件名序列起作用。也许这样的事情会工作:
BEGIN { $^I = \'.oldPW\'; }  # Enable in-place editing
...

local @ARGV = map {
    $Services{$request}{\'configDir\'} . \'/\' . $_ 
} @{$Services{$request}{\'files\'}};
while (<>) {
   s/$oldPass/$newPass/;

   # print? print ARGVOUT? I don\'t remember
   print ARGVOUT;
}
但是,如果这不是一个简单的脚本,并且您需要使用
@ARGV
STDOUT
进行其他用途,则最好使用
Tie::File
这样的命令来完成此任务:
use Tie::File;
foreach (@{$Services{$request}{\'files\'}})
{
    my $filename = $Services{$request}{\'configDir\'} . \'/\' . $_;

    # make the backup yourself
    system(\"cp $filename $filename.oldPW\");   # also consider File::Copy

    my @array;
    tie @array, \'Tie::File\', $filename;

    # now edit @array
    s/$oldPass/$newPass/ for @array;

    # untie to trigger rewriting the file
    untie @array;
}
    
Tie :: File已经提到过,非常简单。对于非命令行脚本,避免使用-i开关可能是一个好主意。如果您想避免使用Tie :: File,则标准解决方案是: 打开文件进行输入 打开一个临时文件进行输出 从输入文件读取一行。 以您喜欢的任何方式修改行。 将新行写到您的临时文件中。 循环到下一行,依此类推。 关闭输入和输出文件。 将输入文件重命名为一些备份名称,例如将.bak附加到文件名之后。 将临时输出文件重命名为原始输入文件名。 无论如何,这实际上是通过-i.bak开关在幕后进行的操作,但是具有更大的灵活性。     

要回复问题请先登录注册