2009-06-29 8 views
1

これはPerlスクリプト自体からPerlを実行すると冗長に見えます。プログラムの中で-piを模倣する実際のPerlコードは何ですか?

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

実際のPerlコードは、-piと同じですか?私はPerlでsedのように動作するものがほしいのと同じくらい簡単です。トッド・ガードナーのサイトに基づいて


、基本的にはすべての行に正規表現を適用しようとすると、ファイルのすべてを読み取り、書き込みようです。解決策は、私のような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); 

を2開きを使用してに何か問題はありますか?これを避けるべきか、それとも単純な解決策には向いていますか?

システムsedコマンドははるかに単純でクリーンであることを認めなければなりません。

+0

2つのファイルを開く場合は、2つのファイルが開かれている必要があります。 Re:sedはシンプルでクリーンです。絶対にそうかもしれませんが、いくつかのプログラムは各ファイルを開き、各行をチェックし、必要に応じて置換を行い、行を出力しなければなりません。魔法の方法はありませんファイル内のデータを見ることなく、ファイルに置換をスリップさせることができます。または、もしあれば、誰かが私たちにそれを教えてくれることを願っています。 – Telemachus

答えて

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; 
+0

簡単なメモTie :: Fileは5.8のコアPerlの一部となりました。 5.8より前のバージョンを使用している場合はアップグレードしてください。または、CPANからTie :: Fileをダウンロードしてください。 –

8

詳細については、perlrunを参照してください。

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

に相当する:

$ perl -p -i.orig -e "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); 
4

Perlmonksと同等の提案があります。また、同じスレッドで推奨

use English qw<$INPLACE_EDIT>; 

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

Sysadm::Install::pie

4

B::Deparseはあなたの友達です:

我々が見ることができる。このことから
[email protected]:~/test$ perl -MO=Deparse -pi -e 1 
BEGIN { $^I = ""; } 
LINE: while (defined($_ = <ARGV>)) { 
    '???'; 
} 
continue { 
    print $_; 
} 
-e syntax OK 

その$^Iは何ですか?インプレース編集が可能です。編集したいファイルに@ARGVを設定してループを外してください。

関連する問題