2016-05-02 5 views
0

Ich bin ein totaler Anfänger bei Perl, versuchen, etwas neuen Code für ein bestimmtes Projekt zu lernen. Kurz gesagt, ich mache ein Skript (auf osx), das alle xml-Dateien in einem Ordner durchsuchen und bestimmte Zahlen zensieren soll. Ich weiß, dass ein One-Liner hätte helfen können, aber die Menge der Dateien wird ziemlich groß sein (Tausende von Dateien), und würde regelmäßig passieren, so ein Skript wäre es schöner. Und außerdem gibt es das Lernen, Teil zu skandieren :)Perl-Skript gibt eine leere Ausgabedatei

Ich habe es geschafft, meine Dateien zu öffnen, die Regex in jeder Zeile auf dem Original für meine spezifischen Bedürfnisse arbeiten und eine beschreibbare TEMP-Datei für meine neuen Informationen generieren. Hier hört es auf zu arbeiten. Ich habe versucht, die neue Datei nach der Schleife über die alte Datei zu kopieren, aber am Ende habe ich eine leere (!) Datei. Ich vermutete einen Fehler mit der Temp-Datei, aber das sieht perfekt aus. Ich probierte sogar, als einen Noobs Ausweg, den Prozess Zeile für Zeile von der Temperatur zurück in die ursprüngliche Datei umzukehren, nachdem ich den geöffneten Modus (gelesen) geändert hatte, aber dass ALSO auch eine leere Datei gab.

Und jetzt ist mein Kopf irgendwie leer. Jede mögliche Hilfe würde geschätzt werden :)

#!/usr/bin/perl 
use strict; 
use warnings; 
use File::Copy; 

chdir "/perltest/test"; #debugsafety 

#file 
my $workingfiles = "*.XML"; 
my @files = glob("$workingfiles"); 

#process files 
my $old; 
my $tmpfile; 

foreach my $file (@files) { 
    print "$file \n"; 

    open ($old, "<", $file) or die "No file"; 
    open ($tmpfile, ">", 'temp.tmp') or die; 
    while(my $line = <$old>) { 
    my $subz = $line; 
    $subz =~ s/([[:upper:]]{2}[[:digit:]]{6})|([[:upper:]]{1}[[:digit:]]{7})|(?:(?<![[:digit:]])[[:digit:]]{8}(?![[:digit:]])|([[:upper:]]{2}[[:digit:]]{5}[AB]))/**CENS**/g; 
    print $subz; 
    print $tmpfile $subz; 
    } 
    print "Start copying.\n"; 

    open (my $old, ">", $file) or die "No file"; 
    open (my $tmpfile, "<", 'temp.tmp') or die; 

    #copy $tmpfile, $old or die "Couldn't copy"; 
    my $y = 0; #debug 
    while (my $line = <$tmpfile>) { 
     print $y++; #debug 
     my $subz = $line; 
     print $subz; 
     print $old $subz; 
    } 
} 

print "Complete.\n"; 
exit; 
+1

Sie deklarieren höhere Scope-Variablen ('$ old' und' $ tmpfile') später in der Schleife ... tun Sie das nicht. Ich würde das zuerst überprüfen. Außerdem werden die Dateihandler geöffnet, aber nicht geschlossen, wenn Lese-/Schreibrollen auf ihnen ausgetauscht werden. – eballes

+0

Warum hast du deine 'copy' Zeile auskommentiert? – toolic

+0

Der Grund, warum ich die Kopie auskommentiert habe, war, dass sie mir eine leere Datei gab. Der Code nach der kommentierten Kopie war mein zweiter Versuch, das Gleiche zu tun :) – LaMa

Antwort

2

Sie öffnen Ihre Aktengriffe, bevor Sie sie schließen. Ich bin ein Oracle DBA, der sich als Perl-Entwickler tarnt, also kann ich das Warum nicht dahinter stecken. Aber ich weiß, wenn Sie Ihre Dateigriffe schließen, sollte Ihr Skript so funktionieren wie es ist.

close ($old); # add this line 
close ($tmpfile); # add this line 

print "Start copying.\n"; 

Es wäre dann eine gute Übung, sie wieder zu schließen, wenn Sie fertig sind, um sie zu "kopieren".

0

Schließen Sie das Dateihandle explizit, wenn Sie mit dem Schreiben fertig sind. Die Dinge werden immer noch gepuffert, bis du das tust. Auch würde mehr Sinn

rename($file, "$file.old"); 
rename("temp.tmp", $file); 

machen, statt durch die Datei Looping (oder mit File :: Copy :: Kopie), um eine Sicherungskopie zu machen.

Schließlich, für einfache Änderungen könnte ich vorschlagen, sich bemühen, es mit der Befehlszeile zu tun, so dass Sie nicht Ihren Kopf kratzen und sich fragen müssen "Was habe ich letztes Mal in diesem Skript?". Es kann auf lange Sicht eine große Zeitersparnis sein.

perl -p -i.bak -e 's/pattern/text/;' files* 

ist die allgemeine Form.

Verwandte Themen