On Son, 22 Jun 2003 at 14:40 (+0200), Bodo Kaelberer wrote: [...]
Zum Prinzip, wie ich es machen wuerde: Lege Dir zuanfangs eines jeden Datensatzes ein assoziatives Array (in Perl Hash genannt?) an und lege fuer jeden moeglichen Schluessel einen Wert '' rein. Schluessel waeren bei Dir 'Kdnr', 'Name', 'Firma' etc. In Perl geht das glaube irgendwie so:
$daten{'Kdnr'} = ''; ...
Im Prinzip ACK, aber s. u. [...]
Dann parst Du aus jeder Zeile das Schluessel-Wert-Paar und haengst den Wert an den bestehenden an.
($key, $value) = split( ':', $line ); $daten{$key} .= $value;
Das uebernimmt elegant das Problem der ueber mehrere Zeilen verteilten Daten. Bei Laune kannst Du auch noch Abfragen, ob es einen solchen Schluessel bereits gibt. Dadurch kannst Du ungueltige Schluessel ausfiltern.
Praktisch: Alle Felder, die nicht aufgetreten sind, haben am Ende eines Eintrages den Wert ''. Die kannst Du so uebernehmen oder durch irgendetwas wie '-' oder 'unbekannt' ersetzen.
Hm, etwas vage ;-) Als erstes ein Tipp: Du solltest immer mit use strict; arbeiten und Deine Variablen sauber deklarieren: my %daten = (); Du ersparst Dir viel Ärger und Fehlersuche damit. Und Du musst bei jedem neuen Datensatz (Also wenn Kdnr auftaucht) den Hash leeren, sonst sind spätestens beim 2. Durchlauf die Keys eben nicht mehr leer. Du kannst ihn nicht lokal in der Schleife deklarieren, weil Du ihn ja nicht bei jedem Durchlauf des foreach neu haben willst. Um die Spaltenanzahl konstant zu halten und nicht Spalten verrutschen zu lassen, empfiehlt sich ein zusätzliches Array: my @spalten = ("Kdnr", "Name", "Firma", "Beschreibung", "Telefon", "Zusatz"); So sollte es gehen: <schnipp> #! /usr/bin/perl use warnings; use strict; # Datei lesen die "usage: $0 Dateiname\n" unless defined $ARGV[0]; open DATEI, "$ARGV[0]" or die "Fehler beim Oeffnen der Datei ($!)\n"; my @zeilen = <DATEI>; close DATEI; # meine Variablen my %daten = (); # der Hash fuer die Werte und Keys eines Datensatzes my @spalten = ("Kdnr", "Name", "Firma", "Beschreibung", "Telefon", "Zusatz"); # Tabellenheader print "<table width='100%' border='1'>\n"; print "<tr>\n"; foreach (@spalten) { printf "<th>%s</th>\n", $_; } print "</tr>\n"; foreach (@zeilen) { # Zeilen abklappern, Zeile wird in $_ abgelegt chomp; # \n wegwerfen next if /^ *$/; # leere Zeilen wegschmeissen if (defined ($daten{'Kdnr'}) && /^Kdnr/) { # $_ faengt mit KdNr an print "<tr>\n"; # Tabellenzeile foreach my $out (@spalten) { # Spalten abklappern if (defined $daten{$out}) { # Key vorhanden? printf "<td>%s</td>\n", $daten{$out}; # Ja: Wert schreiben undef ($daten{$out}); # Hash-Key wegschmeissen } else { print "<td> </td>\n"; # Nein: Leerzeichen } } print "</tr>\n"; # Ende Tabellenzeile } my ($key, $value) = split /:/; # neue Zeile aufspalten $key =~ s/^ *(.*[^ ]) *$/$1/; # Leerzeichen am Anfang und Ende weg $value =~ s/^ *(.*[^ ]) *$/$1/; # dito if (defined $daten{$key}) { $daten{$key} .= ", " . $value; # Wert an Hash anhaengen } else { $daten{$key} = $value; # Hash-Key neu erzeugen } } # letzten Satz auch schreiben print "<tr>\n"; # Tabellenzeile foreach my $out (@spalten) { # Spalten abklappern if (defined $daten{$out}) { # Key vorhanden? printf "<td>%s</td>\n", $daten{$out}; # Ja: Wert schreiben } else { print "<td> </td>\n"; # Nein: Leerzeichen } } print "</tr>\n</table>\n"; # Ende Tabelle exit 0; <schnapp> Das Verhalten, wenn im Wert ein ":" auftaucht, muss noch gesondert abgehandelt werden, sowas habe ich hier weggelassen. Sauberer wäre es noch, die Ausgabe (die ja an 2 Stellen auftritt) in eine Funktion zu packen. Ach ja, wenn auch Tabs statt Leerzeichen auftreten können, sollte statt der " " in den Ersetzungen besser \s genommen werden. Jan