2010-12-08 2 views
25

Ich möchte Änderungen am Inhalt einer Datei vornehmen, indem ich Zeilen ändere, lösche oder einfüge oder an den Anfang der Datei anhefte. Wie kann ich das in Perl machen?In Perl, wie kann ich eine Zeile in einer Datei ändern, löschen oder einfügen oder an den Anfang einer Datei anhängen?


Dies ist ein question vom official FAQ. Wir sind importing the perlfaq to Stack Overflow.

+0

möglich Duplikat [Wie kann ich, löschen oder eine Zeile in einer Datei einzufügen oder zu Beginn einer Datei in Perl anhängen?] (Http://stackoverflow.com/questions/2322140/ how-do-i-change-delete-oder-einfügen-a-line-in-a-file-oder-append-to-the-anfang) –

Antwort

41

(Dies ist die official perlfaq answer, abzüglich aller nachfolgenden Änderungen)

Die Grundidee Einfügen, Ändern oder eine Zeile aus einer Textdatei zu löschen beinhaltet das Lesen und Drucken der Datei auf den Punkt wollen Sie das machen ändern, die Änderung vornehmen, dann den Rest der Datei lesen und drucken. Perl bietet keinen wahlfreien Zugriff auf Zeilen (vor allem, da der Datensatz Eingabetrennzeichen, $/, 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, seine Linien gedruckt wird, 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 Zeilen löschen.

Um Zeilen voranzustellen, 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 kleineren Versionen von "perl" und schreibt sie in Großbuchstaben. Das passiert für jede Zeile, also sei sicher, dass du das in jeder Zeile tun sollst.

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, ist die Eingabezeilennummer $. Sinnvoll. Lesen und drucken Sie zuerst die Zeilen bis zu der Zeile, die Sie ändern möchten. Als nächstes lesen Sie die einzelne Zeile, die Sie ändern möchten, ändern Sie es und drucken Sie es aus. Danach lesen den Rest der Zeilen und jene drucken:

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 $_; 
    } 

Zeilen zu überspringen, die Looping-Steuerelemente verwenden. Der nächste in diesem Beispiel überspringt die Kommentarzeilen, und der letzte stoppt die gesamte Verarbeitung, sobald er entweder __END__ oder __DATA__ erreicht.

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

die gleiche Art von Dingen tun, indem Sie neben einer bestimmten Zeile löschen die Linien überspringen Sie wollen nicht in den Ausgang zu zeigen. 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 (so lange wie du kannst passen das Ganze in Erinnerung!):

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 können auch mit diesen helfen. Wenn Sie jedoch vermeiden können, die gesamte Datei auf einmal zu lesen. Perl wird nicht diesen Speicher dem Betriebssystem zurückgeben, bis der Prozess abgeschlossen ist.

Sie können auch Perl-Einzeiler verwenden, um eine Datei direkt zu ändern. Die folgende ändert alle 'Fred' in 'Barney' in inFile.txt und überschreibt die Datei mit dem neuen Inhalt . Mit dem Schalter -p schließt Perl eine While-Schleife um den Code , den Sie mit -e angeben, und -i aktiviert die direkte Bearbeitung. Die aktuelle Zeile ist in $_. Mit -p druckt Perl automatisch den Wert $_ unter das Ende der Schleife. Weitere Details finden Sie unter perlrun.

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

Um eine Sicherung von inFile.txt zu machen, -ia 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 Eingang Zeilen hinzufügen Nummer, führen Sie dann nur den Vorgang, wenn der Test bestanden:

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

Zeilen vor einer bestimmten Zeile hinzufügen, können Sie eine Zeile hinzufügen können, bevor(oder Zeilen!) Perldruckt $_:

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:

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

nach einer Zeile einzufügen eine bereits in der Datei, verwenden Sie den -n Schalter. Es ist wie -p mit der Ausnahme, dass es $_ am Ende der Schleife nicht gedruckt wird, so müssen Sie das selbst tun. Drucken Sie in diesem Fall zuerst $_ und anschließend 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 

& hellip; oder & hellip;

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

Die 'perl -ni -e 'drucken, bis/d /' inFile .txt' funktionierte in der Tat zum Löschen von übereinstimmenden Zeilen, aber die 'perl -pi -e' als nächstes, außer/d/'inFile.txt' nicht. Es änderte auch nicht "next if", sondern "next if". Dies ist mit Perl 5.10.0. Irgendeine Idee was passiert? –

Verwandte Themen