Какой фактический код Perl будет имитировать -pi внутри программы? - PullRequest
1 голос
/ 29 июня 2009

Это кажется избыточным, запуск Perl из самого сценария Perl.

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

Какой фактический код Perl будет имитировать -pi? Я просто хочу что-то, что будет работать, как sed на Perl, настолько просто, насколько это возможно.


Основываясь на сайте Тодда Гарднера, кажется, что он в основном просто читает и записывает весь файл, пытаясь применить регулярное выражение к каждой строке. Решение было немного сложным для такого начинающего пользователя 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);

Что-то не так с использованием двух открытий? Следует ли этого избегать или это просто для простого решения?

Должен признать, что команда system sed намного проще и понятнее.

Ответы [ 4 ]

8 голосов
/ 29 июня 2009

Проверьте 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);
6 голосов
/ 29 июня 2009

Я бы просто использовал 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;
4 голосов
/ 29 июня 2009

B::Deparse ваш друг:

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

Из этого видно, что $^I - это то, что реализует редактирование на месте. Просто установите @ARGV на файлы, которые вы хотите отредактировать, и зацикливайтесь.

4 голосов
/ 29 июня 2009

Perlmonks имеет предложение, эквивалентное:

use English qw<$INPLACE_EDIT>;

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

Также рекомендуется в том же потоке: Sysadm :: Install :: pie

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...