2010-02-23 2 views
10

Die Leute fragen diese Frage und ich beantworte sie mit der gleichen Antwort von perlfaq5. Jetzt können wir auf Stackoverflow zeigen.Wie kann ich eine Zeile in einer Datei ändern, löschen oder einfügen oder an den Anfang einer Datei in Perl anhängen?

+0

Was ist der Punkt, um 'perlfaqN' hier umzubuchen? Kannst du nicht einfach einen Link zu 'perfaq5' http://perldoc.perl.org/perlfaq5.html#How-do-I-change%2c-delete%2c-or-insert-a-line-in- geben a-Datei% 2c-oder-Anhängen-an-den-Anfang-einer-Datei% 3f an die Fragesteller? – codeholic

+2

Ich hasse immer Links. Websites werden veraltet, URLs ändern sich usw. Ich denke, Stackoverflow sollte Informationen erfassen, damit sie immer vorhanden sind. Denken Sie daran, dies ist ein langfristiges Projekt, bei dem die Antwort in drei Jahren so gut sein sollte wie jetzt. Ein Link garantiert das nicht. Denken Sie daran, dass www.perldoc.com die bevorzugte Seite für Dokumente war, bis sie verschwanden. Das könnte auf jeder Seite passieren. –

+0

Auch den Meta-Thread sehen, wo ich über den Import alle perlfaq fragte: http://meta.stackexchange.com/questions/24244/can-we-import-the-perlfaq-into-stackoverflow –

Antwort

13

Von perlfaq5:

Die Grundidee Einfügen, Ändern oder eine Zeile aus einer Textdatei zu löschen beinhaltet das Lesen und Drucken der Datei auf den Punkt, den Sie die Änderung vornehmen möchten, um die Änderung zu machen, dann lesen und den Rest der Datei drucken. Perl bietet keinen Direktzugriff auf Zeilen (insbesondere, da das Datensatzeingabetrennzeichen $/ veränderbar ist), obwohl Module wie Tie::File es fälschen können.

Ein Perl-Programm, diese Aufgaben zu tun nimmt die Grundform, eine Datei zu öffnen, den Druck seiner Linien, dann die Datei endet:

open my $in, '<', $file  or die "Can't read old file: $!"; 
open my $out, '>', "$file.new" or die "Can't write new file: $!"; 

while(<$in>) 
    { 
    print $out $_; 
    } 

close $out; 

Innerhalb dieser Grundform, die Teile hinzufügen, die Sie einfügen müssen, ändern oder löschen Sie Zeilen.

Um Zeilen vor den Anfang zu setzen, drucken Sie diese Zeilen, bevor Sie die Schleife eingeben, die die vorhandenen Zeilen druckt.

open my $in, '<', $file  or die "Can't read old file: $!"; 
open my $out, '>', "$file.new" or die "Can't write new file: $!"; 

print $out "# Add this line to the top\n"; # <--- HERE'S THE MAGIC 

while(<$in>) 
    { 
    print $out $_; 
    } 

close $out; 

Um bestehende Linien zu ändern, den Code ein, die innerhalb der Linien while Schleife zu ändern. In diesem Fall findet der Code alle kleingeschriebenen Versionen von "Perl" und Großbuchstaben sie. Es passiert für jede Zeile, also seien Sie sicher, dass Sie das in jeder Zeile tun sollten!

open my $in, '<', $file  or die "Can't read old file: $!"; 
open my $out, '>', "$file.new" or die "Can't write new file: $!"; 

print $out "# Add this line to the top\n"; 

while(<$in>) 
    { 
    s/\b(perl)\b/Perl/g; 
    print $out $_; 
    } 

close $out; 

Um nur eine bestimmte Zeile zu ändern, die Eingangszeilennummer, $., ist nützlich. Lesen und drucken Sie zuerst die Zeilen bis zu der Zeile, die Sie ändern möchten. Lesen Sie als Nächstes die einzelne Zeile, die Sie ändern möchten, ändern Sie sie und drucken Sie sie. Lesen Sie danach die restlichen Zeilen und drucken Sie diese:

while(<$in>) # print the lines before the change 
    { 
    print $out $_; 
    last if $. == 4; # line number before change 
    } 

my $line = <$in>; 
$line =~ s/\b(perl)\b/Perl/g; 
print $out $line; 

while(<$in>) # print the rest of the lines 
    { 
    print $out $_; 
    } 

Verwenden Sie zum Überspringen von Zeilen die Schleifensteuerelemente. Die next in diesem Beispiel überspringt Kommentarzeilen, und die last stoppt die gesamte Verarbeitung, sobald sie entweder __END__ oder __DATA__ trifft.

while(<$in>) 
    { 
    next if /^\s+#/;    # skip comment lines 
    last if /^__(END|DATA)__$/; # stop at end of code marker 
    print $out $_; 
    } 

die gleiche Art von Ding eine bestimmte Zeile zu löschen next, indem Sie die Zeilen überspringen Sie nicht wollen, die in der Ausgabe erscheinen. Dieses Beispiel überspringt jede fünfte Zeile:

while(<$in>) 
    { 
    next unless $. % 5; 
    print $out $_; 
    } 

Wenn aus irgendeinem Grund, die Sie wirklich die gesamte Datei auf einmal anstatt Verarbeitung line-by-line wollen, um zu sehen, können Sie es schlürfen in (solange Sie passt das ganze im Speicher kann):

open my $in, '<', $file  or die "Can't read old file: $!" 
open my $out, '>', "$file.new" or die "Can't write new file: $!"; 

my @lines = do { local $/; <$in> }; # slurp! 

    # do your magic here 

print $out @lines; 

Module wie File::Slurp und Tie::File kann auch dabei helfen. Wenn Sie jedoch vermeiden können, die gesamte Datei auf einmal zu lesen. Perl wird diesen Speicher nicht an das Betriebssystem zurückgeben, bis der Prozess abgeschlossen ist.

Sie können auch Perl-Einzeiler verwenden, um eine Datei direkt zu ändern. Das Folgende ändert alle "Fred" zu "Barney" in inFile.txt und überschreibt die Datei mit den neuen Inhalten.Mit dem -p Schalter, Wraps Perl eine while Schleife um den Code geben Sie mit -e und -i schaltet in-Place-Bearbeitung. Die aktuelle Zeile befindet sich in $_. Mit -p druckt Perl am Ende der Schleife automatisch den Wert $_. Weitere Details finden Sie unter perlrun.

perl -pi -e 's/Fred/Barney/' inFile.txt 

Um eine Sicherung von inFile.txt zu machen, -i eine Dateierweiterung geben hinzuzufügen:

perl -pi.bak -e 's/Fred/Barney/' inFile.txt 

Um die fünfte Zeile nur zu ändern, können Sie einen Test überprüft $., die Eingangszeilennummer, fügen Sie dann nur die Operation durchführt, wenn der Test bestanden: (! oder Linien)

perl -pi -e 's/Fred/Barney/ if $. == 5' inFile.txt 

So fügen Sie Zeilen vor einer bestimmten Zeile, können Sie eine Zeile hinzu, bevor Perl druckt $_: eine Zeile nach einem

perl -pi -e 'print "Put before first line\n" if $. == 1' inFile.txt 

einzufügen bereits:

perl -pi -e 'print "Put before third line\n" if $. == 3' inFile.txt 

Sie sogar eine Zeile am Anfang einer Datei, da die aktuelle Zeile druckt am Ende der Schleife hinzufügen Verwenden Sie in der Datei den Schalter -n. Es ist wie -p außer dass es nicht $_ am Ende der Schleife kann nicht gedruckt werden, so haben Sie das selbst zu tun. In diesem Fall drucken Sie zuerst $_ und dann die Zeile, die Sie hinzufügen möchten.

perl -ni -e 'print; print "Put after fifth line\n" if $. == 5' inFile.txt 

Um Zeilen zu löschen, nur diejenigen drucken, die Sie möchten.

perl -ni -e 'print unless /d/' inFile.txt 

    ... or ... 

perl -pi -e 'next unless /d/' inFile.txt 
+0

Nur frage mich, warum es nicht funktioniert, wenn wir 'perl schreiben - Kuchen ... '? – Zaid

+0

-pie funktioniert nicht, weil das -i ein Argument erwartet und es denkt, dass das 'e' dazu gehört. –

Verwandte Themen