1

这似乎是多余的,从 Perl 脚本本身运行 perl。

my $Pref = "&*())(*&^%$#@!"; 
system("perl -pi -e 's|^SERVERNAME.*\$|SERVERNAME \"\Q$Pref\E\"|g' pserver.prefs");

模拟 -pi 的实际 Perl 代码是什么?我只想要在 Perl 上像 sed 一样工作的东西,尽可能简单。


根据 Todd Gardner 的网站,它似乎基本上只是读取和写入所有文件,试图将正则表达式应用于每一行。对于像我这样的新手 Perl 用户来说,这个解决方案有点复杂,所以我使用以下方法简化了它:

my $ftp = "/home/shared/ftp";
my $backup = $ftp . ".bak";
rename($ftp, $backup);
open (FTP, "<", $backup) or die "Can't open $backup: $!"; 
open (FTP_OUT, ">", $ftp) or die "Can't open $ftp: $!"; 
    while (<FTP>)
    {
        $_ =~ s|$panel_user \Q$panel_oldpass\E |$panel_user \Q$panel_newpass\E |g;
        print FTP_OUT $_;
    }
close(FTP);
close(FTP_OUT);

使用两个打开有什么问题吗?应该避免这种情况还是简单的解决方案可以?

我必须承认,系统 sed 命令更简单、更干净。

4

4 回答 4

8

查看perlrun,它详细描述了这些选项。特别是,它列出了一些选项:

从外壳说

$ perl -p -i.orig -e "s/foo/bar/; ... "

和使用程序一样:

#!/usr/bin/perl -pi.orig
s/foo/bar/;

这相当于

#!/usr/bin/perl
$extension = '.orig';
LINE: while (<>) {
if ($ARGV ne $oldargv) {
    if ($extension !~ /\*/) {
    $backup = $ARGV . $extension;
    }
    else {
    ($backup = $extension) =~ s/\*/$ARGV/g;
    }
    rename($ARGV, $backup);
    open(ARGVOUT, ">$ARGV");
    select(ARGVOUT);
    $oldargv = $ARGV;
}
s/foo/bar/;
}
continue {
print;  # this prints to original filename
}
select(STDOUT);
于 2009-06-29T05:16:06.490 回答
6

我只会使用Tie::File

use Tie::File;
use File::Copy;

copy $file, "$file.bak" or die "Failed to copy $file to $file.bak: $!";
tie @array, "Tie::File", $file or die "Can't open $file: $!";
s/foo/bar/ for @array;
于 2009-06-29T07:33:22.173 回答
4

Perlmonks的建议相当于:

use English qw<$INPLACE_EDIT>;

{
    local ($INPLACE_EDIT, @ARGV) = ('.bak', @files);   
    while (<>) {
        s/this/that/;
        print;       
    }
}

在同一线程中还推荐Sysadm::Install::pie

于 2009-06-29T13:41:51.633 回答
4

B::Deparse是你的朋友:

cowens@amans:~/test$ perl -MO=Deparse -pi -e 1
BEGIN { $^I = ""; }
LINE: while (defined($_ = <ARGV>)) {
    '???';
}
continue {
    print $_;
}
-e syntax OK

从这里我们可以看出这$^I就是实现就地编辑的原因。只需设置@ARGV为您要编辑的文件,然后循环即可。

于 2009-06-29T13:46:57.457 回答