Wieso ist dieser Array leer?
Cruz
- perl
0 Jörk Behrends0 Cruz0 Frank Schönmann0 Cruz
0 Calocybe
Hallo Leute,
mir ist grad etwas unerklärliches passiert.
Ich lese erstmal eine kleine Datenbank ein..
open (DB, "<$db") or die "Could not open $db";
@lines = <DB>;
close(DB);
Dann verarbeite ich sie spaltenweise zu Arrays:
$l=0;
foreach $line (@lines) {
chomp($line);
$i=0;
for ($i=0;$i<$columns;$i++) {
(${$headers[$i]}[$l],$line)=split(/\t/,$line,2);
}
$l++;
} # end foreach @lines
Dann noch ein kleines..
$test=join("<br>",@lines);
Und siehe da... @lines ist nach diesem Algorithmus leer! $test enthält jede Menge <br> s, also ist @lines immer noch ein langes Array, aber wo sind die Inhalte hingekommen?
Auf der Suche nach einer Antwort
Cruz
Hallo Cruz!
split lines into arrays
$l=0;
foreach $line (@lines) {
Die Elemente von @lines werden nach und nach $line zugewiesen. Änderungen an $line ändern die Elemente im Array !!!
Das folgende chomp zum Beispiel.
chomp($line);
»» $i=0;
»» for ($i=0;$i<$columns;$i++) {
»» (${$headers[$i]}[$l],$line)=split(/\t/,$line,2);
Hier wird nach und nach $line an den Tabulatoren aufgetrennt. Immer ein Element in das Array für die entsprechende Spalte und der Rest wieder nach $line. So wird $line Stück für Stück kürzer - bis es schließlich leer ist!!!
»» }
$l++;
} # end foreach @lines
Und siehe da... @lines ist nach diesem Algorithmus leer! $test enthält jede Menge
»» s, also ist @lines immer noch ein langes Array, aber wo sind die Inhalte hingekommen?
Wie gesagt, Stück für Stück gelöscht. Die Inhalte liegen nun in Arrays. Das Array @headers enthält pro Spalte ein Array. Dieses Spalten-Array enthält wiederum für jede Zeile ein Element ...
Auf der Suche nach einer Antwort
Ich hoffe, daß Du jetzt fündig geworden bist ;-)
Jörk
Die Elemente von @lines werden nach und nach $line zugewiesen. Änderungen an $line ändern die Elemente im Array !!!
Hallo Jörk,
bist du dir da sicher? Kannst du es beweisen? ;)
In einem Jahr Perl Programmieren ist mir das noch nie aufgefallen, aber es wäre auf jeden Fall eine Antwort auf meine Frage. :)
Danke
Cruz
hi!
Die Elemente von @lines werden nach und nach $line zugewiesen. Änderungen an $line ändern die
Elemente im Array !!!
bist du dir da sicher? Kannst du es beweisen? ;)
perldoc perlsyn:
=== cut ===
Foreach Loops
[...]
The foreach' keyword is actually a synonym for the
for' keyword, so
you can use foreach' for readability or
for' for brevity. (Or because
the Bourne shell is more familiar to you than *csh*, so writing for' comes more naturally.) If VAR is omitted,
$_' is set to each value. If
any element of LIST is an lvalue, you can modify it by modifying VAR
inside the loop. That's because the `foreach' loop index variable is an
implicit alias for each item in the list that you're looping over.
=== cut ===
Beweis:
=== cut ===
#!/usr/bin/perl
@array = (1, 2, 3);
print @array;
for (@array)
{
$_++;
}
print @array;
=== cut ===
bye, Frank!
Ok jetzt bin ich beruhigt Danke schön!!
Gruß an alle Helfer
Cruz
Hallo Cruz!
$test=join("<br>",@lines);
Und siehe da... @lines ist nach diesem Algorithmus leer!
Woher weisst Du das? Vielleicht hat es ja jede Menge Elemente, die nur alle Nullstrings oder undef sind.
Du kannst mit scalar(@lines) die Anzahl der Elemente feststellen. Ist diese groesser 0 (am besten == der Anzahl der Zeilen Deiner DB), hast Du vermutlich keine \t in Deinen Daten, sodass beim split() das $line geleert wird.
Ist aber @lines wirklich leer, liegt der Fehler wohl woanders. Dann solltest Du vielleicht noch etwas mehr vom Source posten. @headers und $columns werden naemlich nirgendwo initialisiert.
So lange
Ist aber @lines wirklich leer, liegt der Fehler wohl woanders. Dann solltest Du vielleicht noch etwas mehr vom Source posten. @headers und $columns werden naemlich nirgendwo initialisiert.
Hallo Calocybe,
Ich habe es gründlich durchgetestet, der Array wird auf jeden Fall in diesem Block leer:
$l=0;
foreach $line (@lines) {
chomp($line);
$i=0;
for ($i=0;$i<$columns;$i++) {
(${$headers[$i]}[$l],$line)=split(/\t/,$line,2);
}
$l++;
} # end foreach @lines
Wenn ich $test=join("<br>",@lines); genau vor dem Block einsetze, erhalte ich die komplette Datenbank, wie erwünscht. Aber wenn ich es direkt nach dem Block einsetze, dann enthält @lines nur noch leere trings.
$headers und $columns werden natürlich vorher initialisiert.
Was ich hier absolut nicht verstehe ist, daß dieser Block keinerlei Anweisung enthält, die die Elemente von @lines irgendwie verändern könnte. Eine Zuweisung zu $line in der foreach Schleife hat doch keinen Einfluss auf die Elemente.....oder?
$x=$y bewirkt ja auch nicht, das $y danach leer ist.
Gruß
Cruz
Hallo Cruz
split lines into arrays
$l=0;
foreach $line (@lines) {
Über $line änderst du auch @lines. Versuch mal statt dieser Zeile folgendes einzufügen
foreach $temp (@lines) {
$line = $temp;
Das sollte das problem lösen. Den hier wird wirklich der Inhalt kopiert und nicht nur darauf verwießen
chomp($line);
»» $i=0;
»» for ($i=0;$i<$columns;$i++) {
»» (${$headers[$i]}[$l],$line)=split(/\t/,$line,2);
»» }
$l++;
} # end foreach @lines
Tschüs
Daniel
Ich meinte übrigens genau was du sagtest,
@lines ist nicht leer, sondern es enthält nur leere Strings.
Hab ich in meinem ersten posting vielleicht nicht so toll ausgedrückt.
Sorry
Cruz