2009-06-02 1 views
0

Ich führe den folgenden Code aus, um eine Datei zu öffnen (zu testen) und zu bearbeiten (suchen und ersetzen). Programm scheint die Datei zu öffnen, löscht aber alles, anstatt es zu ersetzen, alles in der Datei. Ich bin nicht sicher, warum das passiert. Kann mir hier jemand helfen?Warum löscht mein Perl-Skript den Inhalt der gesamten Datei, wenn ich versuche, die Datei zu bearbeiten?

#!use/bin/perl 
use strict; 
use warnings; 

my $line = $ARGV[0]; 
my $find = '\s{6}seqfile\s=\sinfile'; 
my $replace = '\s{6}seqfile\s=\sinfil2'; 

open (FILE, ">/home/shubhi/Desktop/pamlrun/test") || die "cant open file \n"; 
my @body = <FILE>; 
foreach $line(@body) 
{ 
(s/$find/$replace/g); 
{ 
print FILE "$line"; 
} 
} 
close(FILE); 
print "reached here\n"; 
exit; 

Antwort

5

Ihre open() öffnet ein Datei-Handle auf Ihre Datei zu schreiben. Ersetzen

open (FILE, ">/home/shubhi/Desktop/pamlrun/test") || die "cant open file \n"; 

mit

open (FILE, "/home/shubhi/Desktop/pamlrun/test") || die "cant open file \n"; 

Im Code, den Sie geschrieben haben, erstellt er sofort diese Datei für die Ausgabe nur. Sie sollten die Datei öffnen, den Inhalt lesen/bearbeiten und dann aufschreiben. Wenn die Datei groß ist, schreiben Sie in eine neue Datei, während Sie die alte Datei lesen, und ersetzen Sie die alte Datei bei erfolgreicher Beendigung.

1

offen für write = '>' offen für Lese = '<'

7

open(FILE, ">filename") öffnet die Datei im Modus ersetzen, über das Schreiben, was es vorher war.

Sie können auch kein regexp im Substitutionsmuster $replace haben.

Wenn ich Ihre Absicht richtig verstanden habe, dies mit einem Einzeiler ersetzt werden könnte

perl -pi -e 's/(\s{6}seqfile\s=\sinfil)e/${1}2/' /home/shubhi/Desktop/pamlrun/test 
4

Es ist wie Sie Magie Bearbeitung wollen in-place aussieht. Der einfachste Weg, dies zu bekommen, ist $^I mit der Magie der @ARGV zu verwenden und <> (suchen Sie nach null Dateikennung in den I/O Operators section):

#!/usr/bin/perl 

use strict; 
use warnings; 

my $find = qr/\s{6}seqfile\s=\sinfile/; 
my $replace = '  seqfile = infil2'; 

@ARGV = ("/home/shubhi/Desktop/pamlrun/test"); 

$^I = ".bak"; #safe the old files as file.bak 

while (<>) { 
    s/$find/$replace/g; 
    print; 
} 

, auch die Art Ihrer regex gegeben, es sieht aus wie Sie wahrscheinlich [ ] wollen (passen Sie ein Leerzeichen an) oder \t (entsprechen einem Tab) nicht \s. \s passt Tabulatoren, Leerzeichen und andere Leerzeichen an.

Sie können auch Tie::File verwenden, aber es scheint nicht, eine Backup-Funktion zur Verfügung zu stellen:

#!/usr/bin/perl 

use strict; 
use warnings; 

use Tie::File; 

my $find = qr/\s{6}seqfile\s=\sinfile/; 
my $replace = '  seqfile = infil2'; 

tie my @lines, "Tie::File", "testdata" 
    or die "could not open file: $!"; 

for my $line (@lines) { 
    $line =~ s/$find/$replace/g; 
} 

Natürlich können Sie Ihre eigenen Backups mit File::Copy rollen könnte:

#!/usr/bin/perl 

use strict; 
use warnings; 

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

my $find = qr/\s{6}seqfile\s=\sinfile/; 
my $replace = '  seqfile = infil2'; 

copy "testdata", "testdata.bak" 
    or die "could not backup file: $!"; 

tie my @lines, "Tie::File", "testdata" 
    or die "could not open file: $!"; 

for my $line (@lines) { 
    $line =~ s/$find/$replace/g; 
} 

Ich wäre auch nachlässig, wenn ich nicht darauf hingewiesen hätte, dass dies im Grunde ein Einzeiler ist:

perl -pi.bak -e 's/\s{6}seqfile\s=\sinfile/  seqfile = infil2/' testdata 

Dies kann mit Perl 5.10 verkürzt wird weiter durch die Nutzung von \K (Null-Breite positiver Blick hinter) unter:

perl -pi.bak -e 's/\s{6}seqfile\s=\s\Kinfile/infil2/' testdata 
+0

I Tie finden :: einfacher Datei. – Svante

Verwandte Themen