Datei nicht vollständig einlesen
Sascha Hausberg
- perl
Hallo,
ich möchte aus einer Datei bestimmte Bereiche in eine neue Datei kopieren. Dazu lese ich die Datei per Filehandle ein und übergebe sie zeilenweise in die neue Datei.
Die Datei ist folgendermaßen aufgebaut:
TextTextText....1.000000
Zeile1
Zeile2
Zeile3
...
TextTextText....1.000000
Zeile1
Zeile2
Zeile3
...
TextTextText....0.000000
Zeile1
Zeile2
Zeile3
...
TextTextText....0.000000
Zeile1
Zeile2
Zeile3
...
TextTextText....1.000000
Zeile1
Zeile2
Zeile3
...
Die Zeilen mit "1.000000" und folgende Textzeilen möchte ich kopieren, die Zeilen mit "0.000000" und folgende Textzeilen sollen ausgelassen werden. Die Anzahl der mit Zeile1-3 markierten Zeilen ist variabel.
Wie kann ich das in Perl realisieren?
Vielen Dank für die Hilfe
ich möchte aus einer Datei bestimmte Bereiche in eine neue Datei kopieren. Dazu lese ich die Datei per Filehandle ein und übergebe sie zeilenweise in die neue Datei.
Hi, da Du sie ja zeilenweise einliest könntest Du ja prüfen, ob in der aktuellen Zeile der gesuchte Wert vorhanden ist, wenn ja, tu was bis ein anderer Begriff vorkommt ...
ist das deine frage ?
Gustl
ich möchte aus einer Datei bestimmte Bereiche in eine neue Datei kopieren. Dazu lese ich die Datei per Filehandle ein und übergebe sie zeilenweise in die neue Datei.
Hi, da Du sie ja zeilenweise einliest könntest Du ja prüfen, ob in der aktuellen Zeile der gesuchte Wert vorhanden ist, wenn ja, tu was bis ein anderer Begriff vorkommt ...
ist das deine frage ?
Gustl
Ein klares Jein ;)
Der gesuchte Wert ("1.000000") kommt in einer Zeile vor, die folgenden Zeilen sollen aber auch eingelesen werden, bis die Zeile mit dem Wert "0.000000" erreicht wird. Dann soll erst wieder bei der nächsten Zeile mit "1.000000" eingelesen werden.
Bis zum ersten Auftreten von "0.000000" ist es kein Problem, aber wie kann ich dann den Block mit unerwünschten Daten überspringen und später erneut mit dem Einlesen beginnen?
Bitte, zitiere so dass man weiß worauf sich die Antwort bezieht, dass macht es für die mitlesenden einfacher die Zusammenhänge zu verstehen.
Danke.
Ein klares Jein ;)
Der gesuchte Wert ("1.000000") kommt in einer Zeile vor, die folgenden Zeilen sollen aber auch eingelesen werden, bis die Zeile mit dem Wert "0.000000" erreicht wird. Dann soll erst wieder bei der nächsten Zeile mit "1.000000" eingelesen werden.
Bis zum ersten Auftreten von "0.000000" ist es kein Problem, aber wie kann ich dann den Block mit unerwünschten Daten überspringen und später erneut mit dem Einlesen beginnen?
du musst mir Markern arbeiten, in etwa so (ungetestet)
my $read = 0;
while(<FH>)
{
$read = 1 if(/...suchmuster für die Zeile ab der du lesen willst.../);
$read = 0 if(/...suchmuster für die Zeile ab der du nicht lesen willst.../);
if($read)
{
... mach was mit den Zeilen, die du einlesen willst
... z.b. in andere Datei schreiben
}
}
Struppi.
du musst mir Markern arbeiten, in etwa so (ungetestet)
my $read = 0;
while(<FH>)
{
$read = 1 if(/...suchmuster für die Zeile ab der du lesen willst.../);
$read = 0 if(/...suchmuster für die Zeile ab der du nicht lesen willst.../);
if($read)
{
... mach was mit den Zeilen, die du einlesen willst
... z.b. in andere Datei schreiben
}
}Struppi.
Danke, das hat funktioniert!
Wie auch immer, egal was oder wie Du hier vorgehst: Eine wirklich stabile Lösung wird das nicht, ausser Du kannst absolut sicherstellen dass in jeder Kopfzeile der Identifier (Suchbegriff) eine Konstante ist und bleibt.
Ich geh mal davon aus dass Du das nur einmalig anwenden willst um es in eine vernünftige Struktur umzuwandeln ?
Hallo Sascha,
Die Zeilen mit "1.000000" und folgende Textzeilen möchte ich kopieren, die Zeilen mit "0.000000" und folgende Textzeilen sollen ausgelassen werden. Die Anzahl der mit Zeile1-3 markierten Zeilen ist variabel.
Du nimmst eine Variable und liest die Datei zeilenweise ein. Bei Text1/Text0 setzt du sie auf true bzw. false, bei Zeile* änderst du sie nicht. Dann kannst du mittels der Variablen entscheiden, ob du die Zeile rüberkopierst.
Viele Grüße aus Freiburg,
Marian
Hey,
Hausaufgabe: erkläre den Algorithmus im Forum.
#!perl
use strict;
use diagnostics;
my $skipflag = 1; # unvollständigen Datensatz am Anfang berücksichtigen
while (<DATA>) {
if (/1\.000000$/) {
$skipflag = 0;
print;
} elsif (/0\.000000$/) {
$skipflag = 1;
} else {
print unless $skipflag;
};
};
__DATA__
TextTextText....1.000000
Zeile1
Zeile2
Zeile3
...
TextTextText....1.000000
Zeile1
Zeile2
Zeile3
...
TextTextText....0.000000
Zeile1
Zeile2
Zeile3
...
TextTextText....0.000000
Zeile1
Zeile2
Zeile3
...
TextTextText....1.000000
Zeile1
Zeile2
Zeile3
...
Solche Beispiele helfen mir immer am besten:
Langsam, step by step, ohne Schnickschnack.
open(DATEI, "<source_datei.dat");
while(<DATEI>) { push(@liste1,$_); }
close(DATEI);
$schalter;
foreach $zeile1 (@liste1)
{
if ($zeile1 =~ /1.\0000000/) { $schalter=1; }
if ($zeile1 =~ /0.\0000000/) { $schalter=0; }
if ($schalter eq 1) { push(@liste2,$zeile); }
}
open(DATEI, ">dest_datei.dat");
foreach $zeile2 (@liste2)
{
print DATEI"$zeile2\n";
}
close(DATEI);
Langsam, step by step, ohne Schnickschnack.
aber mit 1 2 unzulänglichkeiten.
[code lang=perl]open(DATEI, "<source_datei.dat");
Fragst du nicht ab ob das open gelungen ist?
Das sollte man immer tun.
open(DATEI, "<source_datei.dat") || die "Kann Datei nicht öffnen: $!";
while(<DATEI>) { push(@liste1,$_); }
Das ist Unsinn, in zweierlei hinsicht.
Einmal würde es einfacher so gehen: @liste = <DATEI> anderseits ist davon aber dringend abzuraten vor allem wenn die Datei gross ist
$schalter;
Wo ist das my? Du verwendest kein use strict?
foreach $zeile1 (@liste1)
{
Selbst wenn man es so machen wollte, wäre für sowas kurzes ausreichend $_ zu verwenden.
if ($zeile1 =~ /1.\0000000/) { $schalter=1; }
if ($zeile1 =~ /0.\0000000/) { $schalter=0; }
if ($schalter eq 1) { push(@liste2,$zeile); }
mal abgesehen vom der falschen Variabel (mit use strict wäre das nicht passiert)
eq ist ein Sringvergleich, da aber der schalter nur true oder false sein kann reicht ein einfaches if($schalter) ...
Aber eine u.U. riesige Datei in zwei Array zwischen zu lagern ist mehr als ineffizient.
print DATEI"$zeile2\n";
Da du weiter oben kein chomp benutzt hast du jetzt zwischen jeder Zeile eine Leerzeile.
Alles in allem ein ziemlich mißlungener Versuch.
Struppi.
Hallo Struppi, ja Du verstehst es immer wieder einen aufzubauen :)
Du hast natürlich fachlich in allen Punkten recht, und im entscheidenden Abschnitt hab ich die 0 maskiert und nicht den Punkt :( Grober Fehler von mir.
Ich dachte eben hier gings nicht in erster Linie um Perfektes Perl, sondern ums Ablauf-Verständnis. Und da ist es doch erst mal wirklich wurscht ob ich if ($schalter) oder if ($schalter eq 1) oder if (schalter > 0) schreibe. Das Ergebnis bleibt ja doch das gleiche.
Auch wenns jetzt hier nicht der Sache dient möchte ich mal was bemerken was mir schon sehr lange am Herzen liegt: (Man möge mir bitte diese Regelverletzung verzeihen dass ich kein Menschelei-Thema draus mache)
Ich mach das als Hobby. Ich brauche ein Ablaufverständnis auf meiner Ebene, das ich mir durch solche Beispiele erarbeite, und verzichte deshalb auf "für mein grundsätzliches Ablaufverständnis überflüssiges".
Viele hier behandeln Themen auf einer, sagen wir mal "Etage tiefer", die mich persönlich einfach nur verwirrt und mich mutlos macht anstatt mir zu helfen. (Du erinnerst Dich z.B: an meinen DBI-Versuch).
Dabei kam raus, dass ich (nicht nur) keine Ahnung von Array-Referenzen hatte. Nun, was war daran so schlimm, ich hatte sie halt noch nie benötigt. Wer kann schon alles auf einmal lernen.
Ich denke immer wieder zu bemerken, dass meine einfachen Beispiele Leuten helfen können, die wie ich keine Profis sind, und ich möchte ja auch gerne helfen. Und da mir der Thread-Eröffner nicht wie ein Profi klang versuchte ich es eben.
Also: Natürlich war mein Versuch in Deinen Augen absolut stümperhaft da Du um mindestens 10 mal besser bist als ich. Aber es war ein Versuch und es hat mir richtig weh getan dass Du diesen so zerstampft hast. Mir ist die Freude am helfen erstmal vergangen und ich werde mich hüten es wieder zu tun.
Was nicht heissen soll dass ich Deine Hilfe oder die der anderen für mich nun nicht mehr zu schätzen weiss, ich benötige sie nach wie vor wie man ja deutlich sieht :)
Aber mache bitte Versuche wie meine deshalb nicht gleich so zur Sau.
Ich möchte bitte mit meinen Zeilen hier im Fachbereich keine Diskussion entfachen. Lasst es einfach so stehen. Wenn nicht => Menschelei. Ich bin dann dabei.
Grüsse Gustl - verteidigt heute einmalig die Position der Nicht-Einsteins.
Also: Natürlich war mein Versuch in Deinen Augen absolut stümperhaft da Du um mindestens 10 mal besser bist als ich. Aber es war ein Versuch und es hat mir richtig weh getan dass Du diesen so zerstampft hast. Mir ist die Freude am helfen erstmal vergangen und ich werde mich hüten es wieder zu tun.
Nicht so Schwarz-Weiss denken.
Es geht gar nicht um gut oder nicht gut. Es gibt zwei Grundsätzliche Dinge, einmal finde ich es richtig das das Forum "self" heißt und mehr oder weniger Wert darauf gelegt wird nicht vorgefertigte Lösungen zu präsentieren, sondern den Fragenden die Möglichkeit zu geben die Lösung selbst zu finden und damit evtl. das nächste Problem allein zu lösen zu können. Was für mich nicht heißt, dass auf keinen Fall eine Lösung gezeigt werden darf, aber zumindest ein bisschen Mitarbeit vom Frager erwarte ich.
Das zweite ist, wenn du eine Lösung hier zeigst, dann ist die ja nicht unbedingt für den Einzelfall interessant, sondern es lesen viele hier mit und darüber hinaus wandert das ganze in's Archiv. Daher sollte die "Qualität" einer Lösung minimalen Programmierkonventionen entsprechen. Jeder hat seinen eigenen Stil, aber es gibt einige Grundsätzliche Dinge, die man immer beachten sollte und gerade wenn man merkt, der Frager ist Anfänger ist das wichtig (z.b. use strict, zwingt einen saubereren Code zu schreiben und vermeidet viele Fehler).
Aber mache bitte Versuche wie meine deshalb nicht gleich so zur Sau.
Tut mir leid, ich weiß der Ton war nicht unbedingt freundlich, ich meine das auf keinen Fall persönlich, ich hatte deinen Namen auch gar nicht mehr mit dem DBI Problem in Verbindung gebracht (Mein Namensgedächtnis ist das mißerabelste der Welt).
Versuch einfach ein paar Dinge zu beachten, dann kannst du Anfänger sicher besser helfen als andere, da du die Probleme eher verstehst und vielleicht auch eher noch weißt wie du selber auf die Lösung des Problems kamst.
Aber es gibt eben ein paar Konventionen die das Programmieren einfacher machen, Grundlagen werden z.b. hier http://perldoc.perl.org/perlstyle.html beschrieben.
Wie für fast jede Frage gibt es irgendwo in der Perl Doku eine Antwort, deshalb ist auch das für Anfänger eine gute Übung sich darin zu recht zu finden.
Grüsse Gustl - verteidigt heute einmalig die Position der Nicht-Einsteins.
Kein Problem, schließlich war ich unfreundlich, geht manchmal mit mir durch ;-)
Struppi.
Hallo Gustl,
Solche Beispiele helfen mir immer am besten:
Nein. Für das spezielle Problem vielleicht, sonst aber nicht.
Viele Grüße aus Freiburg,
Marian