Moin Moin!
Abend Forum
Angenommen ich habe eine CSV-Datei mit folgendem Inhalt:
Obstnummer(Zahl einmalig/Identifizierer), Obsthaltbarkeit(Tage), Obstfarbe, ObstnameAlso:
1001, 10, grün, Apfel
1002, 5, rot, Kirsche
1003, 12, gelb, banane
usw...Jetzt ist es mir möglich, nach einem Kriterium zu filtern (Obstname):
zuerst die Zeile einlesen
my $zeile = <LESER>;Zeile aufsplitten:
my ($Obstnummer, $Obsthaltbarkeit, $Obstfarbe, $Obstname) = split(/,/,$zeile);
"Schon falsch!!" ist übertrieben, aber CSV-Dateien liest man typischerweise mit Text::CSV ein. Schlicht und ergreifend, weil CSV-Dateien einige Gemeinheiten enthalten können, die mit einem schlichten split nicht zu erschlagen sind, angefangen bei Quotes und Trennzeichen in gequoteten Werten.
Für Deinen trivialen Fall mag split gerade noch ausreichen.
Ist Dir übrigens bewußt, dass die meisten Felder mit einem Leerzeichen anfangen?
Dannach vergleichen:
if($Obstname eq "Banane") {mach was in diesen geschweiften Klammern steht}
Das wird bei deinem Beispiel nie passieren, denn Du hast nur " banane", was etwas deutlich anderes ist als "Banane".
-> Alle Bananen werden selektiert.Bis hierher kein Problem.
Was, wenn man aber alles Obst herausfiltern will, daß zwingend "rot" sein muss _und_ genau eine Haltbarkeit von "5" Tagen hat. Also beide $-Variablen ($Obstfarbe und $Obsthaltbarkeit) mussen zutreffen, damit die Anweisung in der Klammer ausgeführt werden. Wie schreibe ich das am besten?
Ergänzend zu den reinen Perl-Lösungen:
Du kannst mit DBI und DBD::CSV CSV-Dateien als Mini-Datenbanken benutzen, und damit den Weg für einen leichten Wechsel auf "richtige" Datenbanken legen:
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
use Data::Dumper;
my $dbh=DBI->connect(
'dbi:CSV:', # DB-Treiber und DB-Verbindung ("connect string")
'', # Login (sinnfrei für CSV)
'', # Passwort (sinnfrei für CSV)
{ # Optionen:
# DBI generisch:
RaiseError => 1, # Fehler rufen die() auf
AutoCommit => 1, # Transaktionen explizit starten
FetchHashKeyName => 'NAME_lc', # fetchXXX_hashref liefert Spaltennamen in Kleinbuchstaben
# spezifisch für DBD::CSV:
f_dir => '.', # Dateien (=Tabellen) liegen im aktuellen Verzeichnis
f_ext => '.csv', # Dateien haben die Endung ".csv"
f_encoding => 'utf8', # Dateien sind UTF8-codiert
csv_eol => "\n", # Zeilen enden mit "\n"
csv_sep_char => ',', # Spalten sind mit "," getrennt
csv_quote_char => '"', # Strings sind mit '"' gequoted
csv_escape_char => '"', # '"' innerhalb von Strings wird als '""' geschrieben
csv_tables => {
# Einstellungen für bestimmte Tabellen
obst => {
# Einstellung für Tabelle "obst"
file => 'obst.csv', # Dateiname (redundant)
col_names => [qw( id haltbarkeit farbe name )], # Spaltennamen - stehen normalerweise in der ersten Zeile
skip_first_row => 0, # Erste Zeile enthält schon Datensätze
},
},
}
);
my $sth=$dbh->prepare(q[
SELECT
id,
name
FROM
obst
WHERE
haltbarkeit = ?
AND
farbe = ?
]);
# ^-- Platzhalter benutzen. IMMER. Wenn nicht, sollen Dir die Finger abfaulen.
$sth->execute(5,"rot");
while (my $hr=$sth->fetchrow_hashref()) {
print Dumper($hr);
}
$sth->finish();
$dbh->disconnect();
Zugegeben, für Dein Mini-Problem ist das Overkill.
Aber wenn Du irgendwann einmal von CSV-Dateien weg kommst und eine richtige Datenbank benutzt, mußt Du (idealerweise) nur den connect-Aufruf ändern, und das Programm arbeitet ohne weitere Änderungen z.B. mit PostgreSQL:
my $dbh=DBI->connect(
'dbi:Pg:dbname=obstkiste',
'obstler',
'geheim',
{
RaiseError => 1,
AutoCommit => 1,´
FetchHashKeyName => 'NAME_lc',
pg_enable_utf8 => 1,
}
);
Oder mit Oracle:
my $dbh=DBI->connect(
'dbi:Oracle:obstkiste',
'obstler',
'geheim',
{
RaiseError => 1,
AutoCommit => 1,´
FetchHashKeyName => 'NAME_lc',
}
);
Oder mit SQLite:
my $dbh=DBI->connect(
'dbi:SQLite:dbname=obstkiste.sqlite',
'obstler',
'geheim',
{
RaiseError => 1,
AutoCommit => 1,´
FetchHashKeyName => 'NAME_lc',
}
);
Oder mit jeder x-beliebigen Datenbank, die per ODBC ansprechbar ist:
my $dbh=DBI->connect(
'dbi:ODBC:obstkiste',
'obstler',
'geheim',
{
RaiseError => 1,
AutoCommit => 1,´
FetchHashKeyName => 'NAME_lc',
}
);
Oder mit jeder x-beliebigen Datenbank, die per JDBC ansprechbar ist:
my $dbh=DBI->connect(
'dbi:JDBC:hostname=obstkiste.example.com;port=9001;url=jdbc:opentext:db:',
'obstler',
'geheim',
{
RaiseError => 1,
AutoCommit => 1,´
FetchHashKeyName => 'NAME_lc',
}
);
Und notfalls sogar zur DB-Karrikatur MySQL:
my $dbh=DBI->connect(
'dbi:mysql:database=obstkiste;host=evil.example.com;port=3306',
'obstler',
'geheim',
{
RaiseError => 1,
AutoCommit => 1,´
FetchHashKeyName => 'NAME_lc',
}
);
Zu Platzhaltern siehe z.B. http://perlmonks.org/?node_id=811732 und http://perlmonks.org/?node_id=839078.
Alexander
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".