Hello, On Mon, 23 Jun 2003, Jan Trippler wrote:
# Datei lesen die "usage: $0 Dateiname\n" unless defined $ARGV[0]; open DATEI, "$ARGV[0]" or die "Fehler beim Oeffnen der Datei ($!)\n";
Die Datei sollte man IMO explizit "readonly" oeffnen...
my @zeilen = <DATEI>; close DATEI;
*AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA* Das ist der gleiche Fehler wie von grepmail. Versuch das mal mit ner Datei von ein paar 100 MB!!! Stehen lassen kann man das "open".
# 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
*ARGH* Hier wird's dann wirklich doof, wenn man sowieso zeilenweise liest, kann man gleich die Datei hernehmen. while(<DATEI>) { # Zeilen abklappern, Zeile wird in $_ abgelegt (ja, der Kommentar stimmt so!)
chomp; # \n wegwerfen next if /^ *$/; # leere Zeilen wegschmeissen
Wuerde ich andersrum schreiben, bei leeren Zeilen faellt dann der ueberfluessige Aufruf von 'chomp' weg: next if /^\s*$/; # leere Zeilen wegschmeissen chomp; # \n wegwerfen
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
Ich wuerde eher jew. beim Auftauchen von 'Kdnr' das gesamte hash reinitialisieren: 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 } else { print "<td> </td>\n"; # Nein: Leerzeichen } } print "</tr>\n"; # Ende Tabellenzeile %daten = (); # hash reinitialisieren } ## in $_ steht immer noch das neue Kdnr: ...
my ($key, $value) = split /:/; # neue Zeile aufspalten
Die Deklaration wuerde ich aus der Schleife rausnehmen, das ist nicht noetig. Also das 'my ($key, $value)' vor das while und dann hier nur noch: ($key, $value) = split /:/; # neue Zeile aufspalten
$key =~ s/^ *(.*[^ ]) *$/$1/; # Leerzeichen am Anfang und Ende weg
$key =~ s/^\s*(.*\S)\s*$/$1/;
$value =~ s/^ *(.*[^ ]) *$/$1/; # dito
$value =~ s/^\s*(.*\S)\s*$/$1/;
if (defined $daten{$key}) { $daten{$key} .= ", " . $value; # Wert an Hash anhaengen } else { $daten{$key} = $value; # Hash-Key neu erzeugen } }
Das sollte so weiter funktionieren. Hier ist man dann "durch", und es kann: close(DATEI); folgen.
# letzten Satz auch schreiben [Rest ok] <schnapp>
Das Verhalten, wenn im Wert ein ":" auftaucht, muss noch gesondert abgehandelt werden, sowas habe ich hier weggelassen.
($key, @rest) = split(':'); $value = join('', @rest); '@rest' dabei auch noch vor der Schleife deklarieren
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.
Ja. s.o... Ich fasse nochmal zusammen: ==== ungetestet ==== #! /usr/bin/perl use warnings; use strict; # meine Variablen my %daten = (); # der Hash fuer die Werte und Keys eines Datensatzes my @spalten = ("Kdnr", "Name", "Firma", "Beschreibung", "Telefon", "Zusatz"); my ($key, $val, @rest); sub print_row() { 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"; # Ende Tabellenzeile } # Datei lesen die "usage: $0 Dateiname\n" unless defined $ARGV[0]; open(DATEI, "<$ARGV[0]") or die "Fehler beim Oeffnen der Datei: $!"; # Tabellenheader, ggfs. zum kompletten html-header erweitern print "<table width='100%' border='1'>\n"; print "<tr>\n"; foreach (@spalten) { printf "<th>%s</th>\n", $_; } print "</tr>\n"; while(<DATEI>) { # Zeilen abklappern, Zeile wird in $_ abgelegt next if /^\s*$/; # leere Zeilen wegschmeissen chomp; # \n wegwerfen if (defined ($daten{'Kdnr'}) && /^Kdnr/) { # $_ faengt mit KdNr an, # also ist der letzte Datensatz vollstaendig, also diesen # ausgeben... print_row(); # ... und den hash reinitialisieren %daten = (); } # aktuelle Zeile aufspalten... ($key, @rest) = split(':'); $val = join('', @rest); # ... saeubern ... $key =~ s/^\s*(.*\S)\s*$/$1/; # Leerzeichen am Anfang und Ende weg $val =~ s/^\s*(.*\S)\s*$/$1/; # dito # ... und bis zur Ausgabe via print_row bei naechsten Datensatz in # %daten speichern... if (defined $daten{$key}) { $daten{$key} .= ", " . $val; # Wert an Hash anhaengen } else { $daten{$key} = $val; # Hash-Key neu erzeugen } } close(DATEI); # letzten Satz auch noch ausgeben... print_row(); # ...und die Tabelle "schliessen" print "</table>\n"; # feddich ;) exit 0; ==== Ich denke, fuer dieses kleine scripterl sind die globalen Variablen angebracht... -dnh -- When you say "I wrote a program that crashed Windows", people just stare at you blankly and say "Hey, I got those with the system, *for free*". -Linus Torvalds