什么是在程序中模仿-pi的实际Perl代码?

时间:2009-06-29 05:07:46

标签: regex perl sed

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

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

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


基于Todd Gardner的网站,它似乎基本上只是读取和写入所有文件,试图将正则表达式应用于每一行。对于像我这样的noob 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 个答案:

答案 0 :(得分:8)

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

来自shell,说

$ 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);

答案 1 :(得分: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;

答案 2 :(得分:4)

Perlmonks的建议相当于:

use English qw<$INPLACE_EDIT>;

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

在同一个帖子中也推荐使用Sysadm::Install::pie

答案 3 :(得分: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设置为您要编辑的文件,然后循环播放。