PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Mit Perl Zeilen aus Datei Löschen



wurf
06-09-2003, 14:13
Hallo!

Ich möchte mit Perl eine bestimmte Zeile aus einer Datei löschen also zb. die Zeile 5 aus der Datei 'datei.txt' soll gelöscht werden. Leider bin ich in Perl absoluter Neuling.

Mein bisheriger Ansatz:

#!/usr/bin/perl

$loeschzeile = 5; #Zeile 5 soll gelöscht werden
my $zeilennr = 1;
my $FILE;
open(FILE, "< datei.txt");
while(<FILE> ) {

# in dieser while-Schleife sollte immer wenn $zeilennr nicht $loeschzeile ist die derzeitige
# Zeile (also $_, oder?) in ein neues Array geschrieben werden. Danach wird $zeilennr um
# eins erhöht, und die schleife beginnt von vorne.

}
close(FILE);

Danach soll jetzt dieses mit allen Zeilen außer der Fünften gefüllte Array wieder in die Datei datei.txt geschrieben werden.

Bitte helft mir wie ich die das jetzt umsetzen kann (inhalt der while-schleife und array-in-datei-schreiben).

Vielen Dank für eure Hilfe!

Michi

phate
06-09-2003, 17:29
Hi wurf,

wie fast immer führen hier mehrere Wege zur Lösung.

Im Folgenden eine Liste, der Dinge, die Dich weiterbringen.

- Perls Spezialvariable $.
- Die Funktion push
- Die Funktion foreach bzw. eleganter mit Perls Spezialvariable $,

Genaueres zu den Funktionen
perldoc -f funktionsname. In der FAQ gibts auch nen Abschnitt der auf Deine Frage passt.
perldoc -q fileHow do I change one line in a file/delete a line in a file/insert a line in the middle of a file/append to the beginning of a file?

Eine gute Liste der Spezialvariablen in Perl findet sich unter
http://www.kichwa.com/quik_ref/spec_variables.html

tomes
06-09-2003, 19:56
#!/usr/bin/perl

my $loeschzeile=5; #Zeile 5 soll gelöscht werden
my $i=0;
open(FILE, "< datei.txt");
open(TMP,">tmp.txt");
foreach my $zeile (<FILE>){
$i++;
if ($i != $loeschzeile){print TMP $zeile;}
}
close(FILE);
close(TMP);
`mv tmp.txt datei.txt`;

Allerdings wuerde ich vorher die datei.txt kopieren und zu Schluss pruefen ob alles funktioniert hat. Erst dann die orginal File loeschen/ueberschreiben.

T;o)Mes

phate
06-09-2003, 21:12
Hi ihr beiden,
my $i=0; $i kann man sich sparen, wenn man die Dateien in umgekehrter Reihenfolge öffnet und die interne Perlvariable $. verwendet.
if ($i != $loeschzeile){print TMP $zeile;} Passend zur gerade stattfindenden 'unless'-Diskussion würde man dass dann
print TMP $zeile unless $. == $loeschzeile;schreiben.
`mv tmp.txt datei.txt`;Solche Stilblueten am besten gleich vergessen. Eines der Paradigmen bei der Perl-Programmierung ist portablen Code zu erstellen. Mit direkten Systemaufrufen ist das nicht möglich. Perl stellt mit 'rename' eine Funktion zur Verfügung die plattformübergreifend genau das macht. Lediglich beachten, dass rename nicht partitionsübergreifend verwendet werden kann. Quelle und Ziel müssen also auf der gleichen Partition liegen. Sollte in diesem Fall aber kein Problem sein.

wurf
06-09-2003, 21:42
Hallo!

Vielen Dank für eure schnellen antworten, dein Script tomes hat auf anhieb funktioniert!
Hat mir sehr geholfen.

Tschüss,

Michi

Badsteve
07-09-2003, 12:02
in Kurzform würde das heißen:

perl -e 'while(<>){ print $_ unless $. == 2;}' datei

wobei hier alles nach STDOUT ausgegeben wird.

@ phate


$i kann man sich sparen, wenn man die Dateien in umgekehrter Reihenfolge öffnet und die interne Perlvariable $. verwendet.

Wieso sollte man die Dateien dazu in ungekehrter Reihenfolge öffnen?


Steve

phate
07-09-2003, 13:19
Also wenn wir hier schon kurz, kürzer, am kürzesten machen, dann aber richtig
perl -ni -e 'print unless $.==2' datei Hierbei werden die Änderungen direkt in der Datei durchgeführt. Bzw
perl -ni.bak -e 'print unless $.==2' datei um eine Sicherungsdatei mit der Endung .bak zu erstellen.
Wieso sollte man die Dateien dazu in ungekehrter Reihenfolge öffnen?Weil sich $. immer auf das zuletzt geöffnete Filehandle bezieht. Und das sollte dann auch die Quelldatei sein.

Badsteve
07-09-2003, 15:58
Weil sich $. immer auf das zuletzt geöffnete Filehandle bezieht. Und das sollte dann auch die Quelldatei sein.

ok. Dann hatte ich das falsch verstanden.

Steve