# Standardfunktionen

The problem with OO is that there's already a strong tendency to require to know everything before you can do anything.
Larry Wall

Perl stellt eine Menge Funktionen bereit, die alltägliche Programmieraufgaben erheblich erleichtern. Deshalb beschäftigt sich dieses Kapitel ausschließlich mit diesen Standardfunktionen.

# Zeichenkettenfunktionen

Verschiedene Funktionen ermöglichen es Ihnen, eine Zeichenkette in Groß- oder Kleinbuchstaben umzuwandeln, eine Zeichenkette in einer anderen zu suchen oder eine Zeichenkette zu verschlüsseln.

# Groß- und Kleinbuchstaben

Mit der Funktion lc können Sie alle Buchstaben in einer Zeichenkette in Kleinbuchstaben umwandeln und mit uc in Großbuchstaben. Die Syntax für diese Funktionen lautet:

string lc(string);  
string uc(string);

Der Rückgabewert der Funktionen ist immer die umgewandelte Zeichenkette, die als Parameter übergeben wurde. Ein Beispiel:

my $gross = "NUR GROSSBUCHSTABEN";  
my $klein = "nur kleinbuchstaben";  
print lc($gross);  
print uc($klein);

Anstelle der print-Anweisung können Sie natürlich auch einen Skalar angeben, der die umgewandelte Zeichenkette entgegennimmt.

my $gross = lc($gross);  
my $klein = uc($klein);

Die Bezeichner dieser Funktionen sind Abkürzungen für »lower case« (Kleinbuchstaben) und »upper case« (Großbuchstaben).

Bedenken Sie dabei jedoch, dass die übergebenen Zeichenketten selbst nicht verändert werden. Der Wert wird nur ausgelesen, verändert und zurückgegeben. Erst durch die Zuweisung an die Variable, die als Parameter übergeben wurde, wird auch der Wert der Variablen verändert.

# Zeichenwerte

Alle Buchstaben, Zeichen und Zahlen stehen in einer so genannten Zeichentabelle und werden durch einen 8-Bit-Wert kodiert. Diese Tabelle nennt sich ASCII-Tabelle und umfasst 255 verschiedene internationale Zeichen. Dabei entspricht die Zahl 5 nicht zwangsläufig dem ASCII-Code 5. Um das entsprechende Zeichen eines ASCII-Codes zu ermitteln, müssen Sie die Funktion chr (engl. character = dt. Zeichen) verwenden. Den ASCII-Code eines Zeichens ermitteln Sie über die Funktion ord (engl. ordinal = dt. Zahl). Die entsprechende Syntax für die Funktionen lautet:

integer ord(string);  
string chr(integer);

Das folgende Beispiel ermittelt zu den Zahlen von 0 bis 9 den entsprechenden ASCII-Code.

my @zahlen = (0..9);  
print "Zahl = ASCII-Code<br>";  
foreach(@zahlen) {  
  print "$_ = ",ord($_),"<br>";  
}

Dieses Beispiel erzeugt die folgende Ausgabe:

Zahl = ASCII-Code
0 = 48
1 = 49
2 = 50
3 = 51
...

Umgekehrt ermittelt das nun folgende Beispiel zu einem ASCII-Code das entsprechende Zeichen.

my @ascii = (65..90);  
print "ASCII-Code = Zeichen<br>";  
foreach(@ascii) {  
  print "$_ = ",chr($_),"<br>";  
}

Das Ergebnis dieses Beispiels sind die Buchstaben von A bis Z.

# Länge einer Zeichenkette

Mit der Funktion length können Sie die Länge einer Zeichenkette ermitteln, d. h. die Anzahl der Zeichen der als Parameter übergebenen Zeichenkette. Der Rückgabewert der Funktion ist dann die entsprechende Anzahl.

integer length(string);

Das nun folgende Beispiel ermittelt die Anzahl der Zeichen einer Zeichenkette und gibt diese mittels der print-Anweisung aus.

my $zeichen = "Dies ist eine Zeichenkette.";  
my $anzahl = length($zeichen);  
print $anzahl;

Die Ausgabe lautet:

27

# Teilzeichenkette suchen

Die Funktion index sucht in einer Zeichenkette nach einer Teilzeichenkette. Als Parameter muss die zu durchsuchende Zeichenkette angegeben werden, aber auch die zu suchende Teilzeichenkette. Die Funktion gibt dann die Position der Teilzeichenkette zurück. Ist der Wert kleiner als 0, wurde die Teilzeichenkette nicht gefunden.

integer index(string haystack, string needle);

Dazu ein Beispiel:

my $zeichenkette = "Dies ist eine Zeichenkette.";  
print index($zeichenkette,"Dies");  
print index($zeichenkette,"eine");  
print index($zeichenkette,"dies");

Dieses Beispiel gibt Folgendes aus:

0
9
-1

Wie Sie feststellen können, unterscheidet die Funktion index bei der Suche nach einer Teilzeichenkette zwischen Groß- und Kleinschreibung. Das Wort Dies entspricht also nicht dem Wort dies. Daher werden auch zwei unterschiedliche Werte ausgegeben.

# Teilzeichenkette extrahieren

Um aus einer vorhandenen Zeichenkette eine Teilzeichenkette zu ermitteln, können Sie die Funktion substr verwenden. Das Besondere an der Funktion ist, dass Ihnen mehrere Möglichkeiten der Verwendung zur Verfügung stehen, je nachdem, welche Parameter Sie übergeben.

string substr(string source, integer pos, [integer length, string replace]);

Der Parameter source steht für die Zeichenkette, aus der die Teilzeichenkette ermittelt werden soll, und der Parameter pos gibt die Startposition an. Dabei entspricht das erste Zeichen einer Zeichenkette der Position 0, das zweite der Position 1 usw. Der Parameter length gibt die Länge der zu ermittelnden Teilzeichenkette an und replace eine Zeichenkette, durch die die ermittelte Teilzeichenkette ersetzt wird. Die beiden letzten Parameter sind jedoch optional. Wenn Sie keine Länge angeben, wird die Teilzeichenkette von der angegebenen Position bis zum Ende der Zeichenkette ermittelt.

my $zeichenkette = "Dies ist eine Zeichenkette";  
print substr($zeichenkette,14);  
print substr($zeichenkette,5,3);  
print substr($zeichenkette,14,12,"geänderte Zeichenkette");  
print $zeichenkette;

Die Ausgabe dieses Beispiels:

Zeichenkette
ist
Zeichenkette
Dies ist eine geänderte Zeichenkette

Bitte beachten Sie, dass Sie beim Ersetzen einer Zeichenkette den Parameter length mit an die Funktion substr übergeben müssen, damit diese weiß, wie viele Zeichen durch die neue Zeichenfolge ersetzt werden sollen.

# Zeichenkette verschlüsseln

Die Funktion crypt ermöglicht das Verschlüsseln einer Zeichenkette. Dabei wird eine zweite Zeichenkette zum Verschlüsseln verwendet. Diese zweite Zeichenkette wird häufig als »salt« (dt. Salz) bezeichnet. Bildlich können Sie sich den Vorgang als Versalzen der Suppe vorstellen, da das Ergebnis der Verschlüsselung keine Rückschlüsse auf das Original zuläßt.

Beachten Sie jedoch, dass es keine Möglichkeit gibt, die kodierte Zeichenkette wieder zu dekodieren. Sie müssen die beiden originalen Zeichenketten kennen, um den gleichen verschlüsselten Code ermitteln zu können.

string crypt(string soup, string salt);

Für den Parameter soup setzen Sie die zu verschlüsselnde Zeichenkette ein und für salt die Zeichenkette, mit der verschlüsselt werden soll.

my $soup = "benutzername";  
my $salt = "passwort";  
my $crypted = crypt($soup,$salt);  
print $crypted;

Die erzeugte Ausgabe dieses Beispiels lautet:

paZ9xsy2hvUlw

Da Sie anhand der verschlüsselten Zeichenkette keinerlei Rückschlüsse auf die beiden originalen Zeichenketten ziehen können, ist die Funktion gerade dazu prädestiniert, Passwort-Abfragen zu ermöglichen. Dafür müssen Sie lediglich die verschlüsselte Zeichenkette speichern und vom Benutzer die beiden original Zeichenketten abfragen. Diese beiden Zeichenketten werden erneut verschlüsselt, und das Ergebnis wird mit dem gespeicherten Code verglichen. Stimmen beide überein, hat der Benutzer die korrekten Daten eingegeben.

# Hash- und Listenfunktionen

Gerade dann, wenn Sie mit Listen und Hashes arbeiten, stellt Ihnen Perl überaus nützliche Funktionen zur Verfügung, z. B. zum Einfügen eines neuen Elements an beliebiger Stelle, zum Sortieren einer Liste usw.

# Wert löschen

Sowohl auf Listen als auch auf Hashes können Sie die Funktion undef anwenden. Anstatt jedoch ein komplettes Element zu löschen, entfernt diese Funktion lediglich den Wert des Elements. Das Element selbst bleibt dabei erhalten.

undef(mixed toUndefine);

Als Parameter toUndefine können Sie entweder eine Liste oder einen Hash angeben. Das zu bearbeitende Element geben Sie dabei ebenfalls mit an.

my @staedte = ("Berlin","Paris","Madrid","London");  
print @staedte;  
undef(@staedte[2]);  
print @staedte;

Die Ausgabe dieses Beispiels sieht in etwa folgendermaßen aus:

Berlin, Paris, Madrid, London
Berlin, Paris,   , London

Zwar existiert das Element mit dem Index 2 noch in der Liste, es besitzt jedoch keinen Wert mehr bzw. der Wert ist undefiniert.

# Werte und Schlüssel eines Hashs

Mit den Funktionen keys und values können Sie entweder die Schlüssel oder die Werte eines Hashs ermitteln. Dabei erwarten beide Funktionen einen Hash als Parameter und liefern dann entsprechend die Schlüssel oder die Werte des Hashs zurück. Die Zielvariable muss dementsprechend eine Liste sein.

list keys(hash);      # Ermittelt alle Schlüssel von hash  
list values(hash);    # Ermitteln alle Werte von hash

Das folgende Beispiel speichert die Schlüssel des %ENV-Hashs in der Liste @env_keys und die Werte in der Liste @env_values. Anschließend werden die einzelnen Werte der Listen ausgegeben.

my @env_keys = keys(%ENV);  
my @env_values = values(%ENV);  
print @env_keys,"<br>";  
print @env_values,"<br>";

Beachten Sie bitte, dass zwischen den Listen @env_keys und @env_values keinerlei Bezug besteht. Das Element mit dem Index 5 der Liste @env_values muss also nicht dem Wert des Elements mit dem gleichen Index aus der Liste @env_keys zuzuordnen sein. Möchten Sie auf Nummer sicher gehen, verwenden Sie stattdessen die Funktion each.

# Elemente aus einem Hash entfernen

Mit der Anweisung delete können Sie ein ganzes Element aus einem Hash entfernen bzw. löschen. Wenn das Element erfolgreich gelöscht worden ist, wird der Wert des Elements zurückgegeben, andernfalls ein undefinierter Wert.

my %capitols = (de => "Berlin", fr => "Paris",  
                es => "Madrid");  
if(delete $capitols{es})  
{  
  while(($key,$value) = each(%capitols))  
  {  
    print "$key = $value<br>";  
  }  
}  
else  
{  
  print "Element konnte nicht gelöscht werden!";  
}

Die Ausgabe lautet:

de = Berlin
fr = Paris

Den Rückgabewert der Funktion delete können Sie verwenden, um zu überprüfen, ob das Element gelöscht worden ist, denn ein undefinierter Wert entspricht false und ein definierter Wert true.

# Überprüfen, ob ein Element existiert

Mit der Funktion exists können Sie überprüfen, ob ein Element in einem Hash existiert. Die Funktion liefert true, wenn das Element existiert, andernfalls false.

my %capitols = (de => "Berlin", fr => "Paris",  
                es => "Madrid");  
delete $capitols{es};  
if(exists $capitols{de}) { print "de = $capitols{de}<br>" };  
if(exists $capitols{fr}) { print "fr = $capitols{fr}<br>" };  
if(exists $capitols{es}) { print "es = $capitols{es}<br>" };

Dieses Beispiel erzeugt folgende Ausgabe:

de = Berlin
fr = Paris

Sie sollten immer überprüfen, ob das Element eines Hashs, den Sie nicht genau kennen und auf den Sie zugreifen möchten, überhaupt existiert. Sie vermeiden somit mögliche Fehlerquellen. Wenn Sie die Funktion each verwenden, ist eine Überprüfung natürlich nicht notwendig.

# Alle Elemente eines Hashs ausgeben

Wenn Sie die Schlüssel und Werte eines Hashs ausgeben möchten, ohne zu wissen, über welche Elemente dieser Hash verfügt, sollten Sie die Funktion each verwenden. Diese Funktion gibt so lange alle Elemente zurück, bis keines mehr vorhanden ist.

(string key[, string value]) each(hash aHash);

Wenn Sie den Rückgabewert der each-Funktion nur einem Skalar zuweisen, erhalten Sie lediglich die Schlüsselnamen. Werden zwei Skalare als Empfänger notiert, erhalten Sie sowohl den Schlüsselnamen als auch den Wert des Elements.

my %hash = (nachname => "Mustermann", vorname => "Max");  
my $key,$value;  
while($key = each(%hash)) {  
  print "$key<br>"; }  
while(($key,$value) = each(%hash)) {  
  print "$key = $value<br>"; }

Das Beispiel erzeugt die folgende Ausgabe:

nachname
vorname
nachname = Mustermann
vorname = Max

# Ein Element am Anfang einer Liste hinzufügen oder löschen

Die Funktion shift kennen Sie bereits. Mit dieser Funktion können Sie das erste Element einer Liste löschen und gleichzeitig den Wert auslesen. Dabei erwartet sie als Parameter lediglich die Liste, deren erstes Element gelöscht werden soll.

Genau das Gegenteil der shift-Funktion bewirkt die Funktion unshift. Sie fügt ein Element an den Anfang der Liste ein. Als ersten Parameter erwartet sie die Liste, zu der das Element hinzugefügt werden soll, und als zweiten Parameter den Wert des neuen Elements.

my @cities = ("Berlin","Paris","London");  
shift(@cities);  
print @cities;  
unshift(@cities,"Berlin");  
print @cities;

Die Ausgabe dieses Beispiels sieht folgendermaßen aus:

Paris London
Berlin Paris London

# Ein Element am Ende einer Liste hinzufügen oder löschen

Die Funktion pop löscht das letzte Element einer Liste und gibt den Wert des gelöschten Elements zurück. Als Parameter müssen Sie dabei lediglich die Liste angeben, auf die diese Funktion angewendet werden soll. Mit der Funktion push können Sie ein Element oder mehrere an eine Liste anfügen. Als ersten Parameter erwartet sie die zu bearbeitende Liste und als zweiten Parameter entweder ein Element oder mehrere neue.

my @cities = ("Berlin","Paris");  
my @additionalCities = ("Madrid","London");  
print @cities;  
pop(@cities);  
push(@cities,@additionalCities);  
print @cities;  
push(@cities,"Paris");  
print @cities;

Die Ausgabe lautet:

Berlin Paris
Berlin Madrid London
Berlin Madrid London Paris

# Eine Liste sortieren oder umkehren

Die Reihenfolge der Elemente einer Liste hängt von derjenigen Reihenfolge ab, in der ihr die Elemente hinzugefügt wurden. Mit der Funktion reverse können Sie diese Reihenfolge jedoch ändern, und zwar umdrehen, also von hinten nach vorne. Als Parameter erwartet diese Funktion lediglich die zu bearbeitende Liste.

my @cities = ("Berlin","Paris","London");  
print @cities;  
@cities = reverse(@cities);  
print @cities;

Folgende Ausgabe erzeugt dieses Beispiel:

Berlin Paris London
London Paris Berlin

Mit der Funktion sort können Sie die Reihenfolge auch anhand der ASCII-Tabelle beeinflussen. Dies entspricht einer alphabetischen Sortierung, wobei aber auch zwischen Groß- und Kleinschreibung unterschieden wird. Auch diese Funktion erwartet als Parameter eine Liste, und zwar die Liste, die sortiert werden soll.

my @cities = ("Paris","Berlin","London");  
print @cities;  
@cities = sort(@cities);  
print @cities;

Die Ausgabe lautet:

Paris Berlin London
Berlin London Paris

# Liste in Zeichenkette konvertieren und umgekehrt

Mit der Funktion join können Sie die Elemente einer Liste zu einer Zeichenkette kombinieren. Damit auch in dieser Zeichenkette die einzelnen Elemente unterschieden werden können, erwartet die Funktion als ersten Parameter ein Trennungszeichen und als zweiten Parameter die Liste, die zusammengeführt werden soll.

my @cities = ("Paris","Berlin","London");  
my $kette = join(";",@cities);  
print $kette;

Dieses Beispiel erzeugt folgende Ausgabe:

Paris;Berlin;London

Umgekehrt können Sie mit der Funktion split diese Zeichenkette wieder in eine Liste umwandeln. Als erster Parameter wird das Trennzeichen erwartet und als zweiter Parameter die Zeichenkette, die die Elemente, getrennt durch das angegebene Trennzeichen, enthält. Das Trennzeichen muss jedoch als regulärer Ausdruck angegeben werden. Da ich erst später auf reguläre Ausdrücke eingehen werde, soll an dieser Stelle erst einmal nur erwähnt werden, dass das Trennzeichen mit einfachen Schrägstrichen umgeben werden muss.

my @cities = ("Paris","Berlin","London");  
my $kette = join(";",@cities);  
my @aufgeteilt = split(/;/,@cities);  
print @aufgeteilt;

Die Ausgabe lautet:

Paris
Berlin
London

# Eine Zeichenkettenfunktion auf alle Listenelemente anwenden

Mit der Funktion map können Sie eine Zeichenkettenfunktion auf alle Elemente einer Liste anwenden. So können Sie z. B. die Funktion uc (Buchstaben in Großbuchstaben umwandeln) gleichzeitig auf jedes Element anwenden. Als erster Parameter wird die Funktion und als zweiter Parameter die Liste erwartet.

my @cities = ("Paris","Berlin","London");  
@cities = map(uc,@cities);  
print @cities;

Die Ausgabe lautet:

PARIS
BERLIN
LONDON

# Datums- und Zeitfunktionen

Wenn Sie in Perl ein Datum oder eine Uhrzeit berechnen möchten, müssen Sie sich mit dem UNIX-Zeitformat bekannt machen. Das Besondere an diesem Format ist, dass alle Zeitberechnungen in Relation zum 01.01.1970 um 00:00:00 Uhr erfolgen. Wenn Sie z. B. den aktuellen Zeitpunkt ermitteln möchten, erhalten Sie einen Wert in Sekunden. Dieser Wert entspricht der Anzahl der Sekunden, die seit dem 01.01.1970 um 00:00:00 Uhr vergangen sind. Ein Wert von 120 (Sekunden) entspricht also dem 01.01.1970 um 00:02:00 Uhr und ein Wert von 2.687.000 dem 01.02.1970 um 00:00:00 Uhr. Ein negativer Wert stünde dementsprechend für ein Datum vor dem 01.01.1970 (00:00 Uhr). Der Wert –120 wäre also der 31.12.1969 um 23:58:00 Uhr und –2.687.000 der 01.12.1969 um 00:00:00 Uhr.

Den aktuellen Zeitpunkt können Sie mit der Funktion time in Erfahrung bringen. Sie liefert als Rückgabewert die Sekunden, die seit dem 01.01.1970 um 00:00:00 Uhr bis zum Zeitpunkt der Ausführung der Funktion verstrichen sind.

#!/usr/bin/perl -w
use CGI qw(:standard);

print header();

my $sekunden = time();
my $tage = $sekunden / 86400;

print "Seit dem 1.1.1970 um 0:00 Uhr sind $sekunden Sekunden bzw. $tage Tage vergangen.";

Listing 5.1: Perl-Script, das den aktuellen Zeitpunkt ermittelt

Eine mögliche Ausgabe des Listings könnte folgende sein:

Seit dem 1.1.1970 um 0:00 Uhr sind 1032803980 Sekunden bzw. 11953.7497685185 Tage vergangen.

Dem Skalar $sekunden werden zuerst mit der Funktion time die verstrichenen Sekunden zugewiesen. Anschließend wird die Anzahl der vergangenen Tage errechnet. Da ein Tag 86.400 Sekunden entspricht, wird der ermittelte Sekundenwert einfach durch 86.400 geteilt. Zum Schluss werden beide Werte ausgegeben.

Leider lässt sich mit diesen Werten, selbst wenn sie umgerechnet wurden, leidlich wenig anfangen. Aus diesem Grund werde ich Ihnen noch zwei weitere Funktionen zeigen, mit denen Sie die Ausgabe der Sekunden etwas ansprechender und für den Benutzer besser lesbar gestalten können.

Mit der Funktion localtime können Sie das Datum und die Uhrzeit im lokalen Format und in der lokalen Zeitzone ermitteln. Als Parameter wird ihr die ermittelte Zeit in Sekunden übergeben. Das errechnete Datum und die Uhrzeit werden dann als Liste zurückgegeben. Ein kurzes Beispiel:

#!/usr/bin/perl -w
use CGI qw(:standard);

print header();

my @datetime = localtime(time);

foreach(@datetime) {
  print "$_ "; }

Listing 5.2: Ermitteln brauchbarer Daten für Datum und Uhrzeit

Besonders viel lässt sich an dieser Stelle auch mit den Daten der Funktion localtime nicht anfangen, außer man kennt die Reihenfolge, in der die Funktion die Daten in der Liste @datetime speichert. Diese finden Sie in der folgenden Tabelle 5.1.

Listenindex Wert
0 Sekunden
1 Minuten
2 Stunden
3 Tag des Monats
4 Monatszahl von 0 bis 11 (0 = Januar, 11 = Dezember)
5 Jahr
6 Wochentag von 0 bis 6 (0 = Sonntag, 6 = Samstag)
7 Tag des Jahres
8 Sommerzeit (1=Ja/0=Nein)

Tabelle 5.1: Aufschlüsselung der Listenelemente

Das nun folgende Listing 5.3 erzeugt eine sehr viel bessere Ausgabe des Datums, der Uhrzeit und der zusätzlichen Informationen.

#!/usr/bin/perl -w
use CGI qw(:standard);

print header();

my @jetzt = localtime(time);
my @wochentage = ("Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag");
my @monate = ("Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember");

my $sekunden = $jetzt[0] < 10 ? "0".$jetzt[0] : $jetzt[0];
my $minuten = $jetzt[1] < 10 ? "0".$jetzt[1] : $jetzt[1];
my $stunden = $jetzt[2] < 10 ? "0".$jetzt[2] : $jetzt[2];

my $tag = $jetzt[3];
my $wochentag = $wochentage[$jetzt[6]];
my $monat = $monate[$jetzt[4]];
my $jahr = $jetzt[5] + 1900;
my $jzeit = $jetzt[8] = 0 ? "Winterzeit" : "Sommerzeit";

print "Es ist <b>$stunden:$minuten:$sekunden</b> Uhr<br>";
print "am <b>$wochentag, den $tag. $monat $jahr</b>.<br>";
print "Dies ist außerdem der <b>$jetzt[7]. Tag</b> des Jahres<br>";
print "und wir haben <b>$jzeit</b>.";

Listing 5.3: Formatierte Ausgabe von Uhrzeit, Datum und Zusatzinformationen

Der Liste @jetzt werden die von der Funktion zurückgegebenen Elemente zugeordnet. Sie enthält nun also alle Informationen, die Sie benötigen. Zusätzlich werden noch zwei weitere Listen definiert: @wochentage und @monate. Diese beiden Listen werden benötigt, da Perl lediglich eine Zahl für den Monat bzw. den Wochentag zurückgibt. Die Reihenfolge der Elemente dieser beiden Listen ist wichtig, da ansonsten die falschen Monatsnamen bzw. Wochentage ermittelt werden. Etwas weiter unten im Quelltext werden Sie den genauen Grund dafür erkennen.

Alle Werte, die Perl in der @jetzt-Liste speichert, sind Zahlenwerte. Für die Ausgabe ist dies aber ein wenig ungünstig, da eine Uhrzeit in dem Format 09:05:03 dargestellt wird und nicht so: 9:5:3. Aus diesem Grund müssen Sie diese Werte in eine Zeichenkette umwandeln und – je nachdem – eine führende 0 hinzufügen, wenn der Wert der Sekunden, Minuten oder Stunden kleiner als 10 ist.

Um für die bessere Übersicht und die Lesbarkeit des Quelltextes zu sorgen, sollten Sie am besten eine einfache Entweder-oder-Anweisung verwenden. Damit können Sie längere if-Anweisungsblöcke umgehen.

my $sekunden = $jetzt[0] < 10 ? "0".$jetzt[0] : $jetzt[0];  
my $minuten = $jetzt[1] < 10 ? "0".$jetzt[1] : $jetzt[1];  
my $stunden = $jetzt[2] < 10 ? "0".$jetzt[2] : $jetzt[2];

Nach dem Zuweisungsoperator = folgt die Bedingung, die überprüft, ob $jetzt[0], $jetzt[1] und $jetzt[2] kleiner als 10 sind. Danach folgen ein Fragezeichen ? und der Wert, der der Variablen ($sekunden, $minuten oder $stunden) zugewiesen werden soll, wenn die Bedingung wahr ist. Ist die Bedingung unwahr, wird der Variablen der Wert zugewiesen, der nach dem Doppelpunkt : folgt. Mit diesen drei Zeilen haben Sie nun die Ausgabe für die Uhrzeit formatiert.

Den Tag lesen Sie einfach über $jetzt[3] aus, da Sie diesen Wert nicht weiter bearbeiten müssen. Bei dem Wochentag sieht das schon etwas anders aus. Perl liefert Ihnen dafür einen Wert von 0 bis 6, wobei 0 dem Sonntag, 1 dem Montag und 6 dem Samstag entspricht. In dieser Reihenfolge wurden auch die Tage in der Liste @wochentage definiert. Den korrekten Wochentag können Sie also ermitteln, indem Sie $jetzt[6] als Index für $wochentage[] angeben.

my $wochentag = $wochentage[$jetzt[6]];  
my $monat = $monate[$jetzt[4]];

Ähnlich ist auch bei den Monatsnamen vorzugehen. Auch hier liefert Perl nur eine Zahl, und zwar von 0 bis 11, wobei 0 dem Januar und 11 dem Dezember entspricht. Auch diesen Wert notieren Sie als Index für $monate[].

In unserem Sprachraum werden Jahreszahlen in der Regel vierstellig angegeben, z. B. als 1980, 1995 oder 2002. Perl liefert jedoch nur die beiden letzten Ziffern und ist in dieser Hinsicht auch nicht besonders konsequent. Während Sie für das Jahr 1980 den Wert 80 und für 1995 den Wert 95 erhalten, liefert Perl für 2002 den Wert 102. Indem Sie 1900 zu dem Wert hinzuaddieren, erhalten Sie die korrekte vierstellige Jahreszahl.

my $jahr = $jetzt[5] + 1900;

Der letzte Wert, den Sie aus der Liste @jetzt auslesen können, bezieht sich auf die Sommer- und Winterzeit. Laufen die Uhren nach Sommerzeit, entspricht dies dem Wert 1. Laufen sie nach Winterzeit, entspricht der Rückgabewert dem Wert 0. Durch eine einfache Entweder-oder-Abfrage können Sie die entsprechende Zeiteinstellung als Wort ermitteln.

my $jzeit = $jetzt[8] = 0 ? "Winterzeit" : "Sommerzeit";

Beim Vergleich zur Ermittlung des Zeitpunktes entsprechend der lokalen Zeitzone können Sie die Uhrzeit auch nach der Greenwich-Meantime (entspricht der westeuropäischen Zeitzone) ermitteln. Notfalls müssen dann jedoch Anpassungen der Stunden vorgenommen werden. Die entsprechende Funktion lautet gmtime. Der Zeitunterschied von Deutschland zur GMT beträgt +2 Stunden.

#!/usr/bin/perl -w
use CGI qw(:standard);

print header();

my @lokal = localtime(time);
my @gmt = gmtime(time);

my $l_sek = $lokal[0] < 10 ? "0".$lokal[0] : $lokal[0];
my $l_min = $lokal[1] < 10 ? "0".$lokal[1] : $lokal[1];
my $l_std = $lokal[2] < 10 ? "0".$lokal[2] : $lokal[2];

my $gmt_sek = $gmt[0] < 10 ? "0".$gmt[0] : $gmt[0];
my $gmt_min = $gmt[1] < 10 ? "0".$gmt[1] : $gmt[1];
my $gmt_std = $gmt[2] < 10 ? "0".$gmt[2] : $gmt[2];

print "Lokale Uhrzeit: $l_std:$l_min:$l_sek<br>";
print "Greenwich-Meantime: $gmt_std:$gmt_min:$gmt_sek";

Listing 5.4: Uhrzeit nach lokaler Zeit und nach Greenwich Meantime

# Mathematische Funktionen

Auch wenn mathematische Berechnungen eher selten in einem Perl-Script – gerade in Hinblick auf dynamische Webseiten – zum Einsatz kommen, soll doch die eine oder andere Funktion an dieser Stelle erwähnt werden.

# Zufallszahlen

Mit der Funktion rand (engl. random = dt. zufällig) können Sie beliebige Zufallszahlen generieren. Dabei können Sie mit einem Parameter einen Zahlenbereich festlegen, in dem die Zufallszahlen liegen müssen. Wenn Sie diese Angabe nicht machen, erhalten Sie nur Zufallszahlen zwischen 0 und 1, ansonsten von 0 bis zur angegebenen Grenze.

Beachten Sie dabei aber, dass die generierten Zufallszahlen keine Ganzzahlen sondern Dezimalzahlen (Fließkommazahlen) sind. Wenn Sie der Funktion rand bei dem Aufruf keine obere Grenze übergeben, bedeutet das nicht, dass Sie lediglich eine 0 oder 1 als Zufallszahl erhalten.

#!/usr/bin/perl -w
use CGI qw(:standard);

print header();

my $zufall1 = rand();
my $zufall2 = rand();
my $zufall3 = rand(100);

print "$zufall1<br>";
print "$zufall2<br>";
print "$zufall3<br>";

Listing 5.5: Perl-Script, das drei Zufallszahlen ermittelt

Den drei Skalaren $zufall1, $zufall2 und $zufall3 wird jeweils eine Zufallszahl zugewiesen und werden anschließend mit der print-Anweisung ausgegeben.

Das eigentliche Problem ist, dass Computer – pragmatisch betrachtet – keine Zufallszahlen errechnen können. Dies ist auch einleuchtend, denn wie soll eine auf Logik basierende Maschine ein zufälliges Ereignis, in unserem Fall eine Zahl, erzeugen? Daher wird zum Generieren einer Zufallszahl meistens die Uhrzeit verwendet, da sie niemals den gleichen Wert besitzt. Mit einem Algorithmus wird anschließend einfach eine »zufällige« Zahl berechnet.

Diesen Vorgang kann man sehr gut an dem folgenden Beispiel nachvollziehen. Mit der Funktion srand können Sie eine Zahl als Initialisierungswert für die Berechnung der Zufallszahlen festlegen.

#!/usr/bin/perl -w
use CGI qw(:standard);

print header();

srand(100);
my $zufall1 = rand();
my $zufall2 = rand();
srand(100);
my $zufall3 = rand();
my $zufall4 = rand();

print "$zufall1<br>";
print "$zufall2<br>";
print "$zufall3<br>";
print "$zufall4<br>";

Listing 5.6: Zufallszahlen mit Festlegung eines Startwertes

Nach der Initialisierung mit srand(100) werden zwei Zufallszahlen berechnet, die einmal dem Skalar $zufall1 und einmal dem Skalar $zufall2 zugewiesen werden. Anschließend erfolgt eine erneute Initialisierung mit dem gleichen Wert wie zuvor (100), und es werden wieder zwei Zufallszahlen generiert. Wenn Sie sich nun die Ausgabe des Scripts ansehen, werden Sie feststellen können, dass sowohl $zufall1 und $zufall3 als auch $zufall2 und $zufall4 den gleichen Wert besitzen.

# Sinus und Kosinus

Die Berechnung des Sinus oder Kosinus unter Perl ist sehr einfach. Als Parameter übergeben Sie einfach die Zahl, von der der Sinus oder Kosinus errechnet werden soll, und die Funktion liefert das entsprechende Ergebnis zurück. Zur Berechnung des Sinus müssen Sie die Funktion sin und für den Kosinus die Funktion cos verwenden. Dazu ein kleines Beispiel:

print sin(90);  
print cos(0);

Dieses Beispiel würde einmal den Sinus des Wertes 90 und einmal den Kosinus des Wertes 0 ausgeben.

# Wurzelberechnung

Zur Berechnung von Wurzeln stehen Ihnen zwei Möglichkeiten zur Verfügung. Entweder verwenden Sie die Funktion sqrt (engl. squareroot), um die Quadratwurzel einer als Parameter übergebenen Zahl zu berechnen, oder Sie bedienen sich einer einfachen mathematischen Schreibweise. Ein Beispiel für sqrt:

my $root = sqrt(16);

Der Skalar $root enthält nun den Wert 4. Die mathematische Schreibweise, äquivalent zum vorherigen Beispiel, würde so lauten:

my $root = 16 ** (1/2);

Auf diese Art und Weise können Sie auch die 3., 4. oder 5. Wurzel errechnen. Für die 3. Wurzel würde die Formel z. B. 16 ** (1/3), für die 4. Wurzel 16 ** (1/4) usw. lauten.

# Umwandlungsfunktionen

# Hexadezimal in dezimal

Eine hexadezimale Zahl, die in Form einer Zeichenkette vorliegt, können Sie mit der Funktion hex in eine Dezimalzahl umwandeln. Die Zeichenkette, die die hexadezimale Zahl »beschreibt«, wird dabei als Parameter übergeben. Der Rückgabewert der Funktion ist dann die Dezimalzahl.

integer hex(string);

Dabei müssen Sie aber die unterschiedlichen Schreibweisen von Hexadezimalzahlen bei HTML und Perl beachten. Während in HTML hexadezimale Werte immer nur als Tripel-Werte vorkommen und mit einem #-Zeichen gekennzeichnet werden, lautet die Schreibweise in Perl z. B. 0xFF oder FF. Die Schreibweise, bei der 0x vor den hexadezimalen Wert gesetzt wird, ist typisch für UNIX/Linux. Außerdem sind Sie in Perl auch nicht nur auf zwei Stellen pro Hexadezimalzahl beschränkt.

my $hex1 = "0x1267";  
my $hex2 = "0x7D2";  
my $hex3 = "0xABC";  
print "<b>HEX = DEZ</b><br>";  
print $hex1," = ",hex($hex1),"<br>";  
print $hex2," = ",hex($hex2),"<br>";  
print $hex3," = ",hex($hex3),"<br>";

In diesem Beispiel werden drei Skalare definiert, denen drei unterschiedliche hexadezimale Werte in Form einer Zeichenkette zugewiesen werden. Anschließend werden die drei Werte in Dezimalzahlen umgerechnet und ausgegeben. Im Browser könnte das folgendermaßen aussehen:

HEX = DEZ
0x1267 = 4711
0x7D2 = 2002
0xABC = 2748

# Oktalzahl in dezimal

Äquivalent zur Konvertierung von Hexadezimalzahlen in Dezimalzahlen können Sie auch Oktalzahlen, die als Zeichenketten vorliegen, umrechnen. Auch hier wird die Zeichenkette, die die Oktalzahl darstellt, als Parameter an die Funktion oct übergeben.

integer oct(string);

Oktalzahlen sind Zahlen auf der Basis 8 und werden in UNIX/Linux häufig dazu verwendet, die Zugriffsrechte auf Dateien oder Ordner festzulegen.

my $oct1 = "755";  
my $oct2 = "777";  
my $oct3 = "0555";  
print "<b>OCT = DEZ</b><br>";  
print $oct1," = ",oct($oct1),"<br>";  
print $oct2," = ",oct($oct2),"<br>";  
print $oct3," = ",oct($oct3),"<br>";

Auch in diesem Beispiel werden zuerst drei Oktalzahlen in der Form von Zeichenketten definiert, mit der Funktion oct umgerechnet und ausgegeben. Die daraus resultierende Ausgabe sieht so aus:

OCT = DEZ
755 = 493
777 = 511
0555 = 365

# Zeichenkette in Zahlenwert umwandeln

Sollte ein Benutzer in einem HTML-Formular mal eine Zahl eingeben müssen, ist dies für ihn kein größeres Problem. Möchten Sie diesen Wert jedoch als Zahl verwenden, stehen Sie vor dem Problem, dass Formulareingaben in HTML immer als Zeichenketten zur Verfügung gestellt werden. Mit der int-Funktion können Sie Zeichenketten aber in Zahlenwerte umwandeln.

integer int(string);

Die Funktion wandelt die übergebene Zeichenkette dabei so lange um, bis sie auf ein Zeichen stößt, das keine Zahl ist.

my $str1 = "123";  
my $str2 = "4711D";  
my $str3 = "12AB5";  
print "<b>STR = DEZ</b><br>";  
print $str1," = ",int($str1),"<br>";  
print $str2," = ",int($str2),"<br>";  
print $str3," = ",int($str3),"<br>";

Zuerst werden drei Zeichenketten definiert, und ihnen wird ein jeweils anderer Wert zugewiesen. Mit der int-Funktion werden diese Zeichenketten in Zahlenwerte umgerechnet und ausgegeben. Die Ausgabe sieht folgendermaßen aus:

STR = DEZ
123 = 123
4711D = 4711
12AB5 = 12

Bei der dritten Zeichenkette können Sie feststellen, dass der sich ergebende Zahlenwert anstatt 125 nur 12 ist. Dies liegt daran, dass die Funktion mit der Umwandlung dann abbricht, wenn sie auf ein Zeichen stößt, das keine Zahl ist. Die danach folgenden Zeichen werden dann ebenfalls ignoriert.

Sie können die int-Funktion jedoch auch dafür verwenden, den ganzzahligen Anteil, z. B. einer Kommazahl zu ermitteln.

my $zahl1 = 1024;  
my $zahl2 = 10.25;  
my $zahl3 = -20.2;  
print $zahl1," = ",int($zahl1),"<br>";  
print $zahl2," = ",int($zahl2),"<br>";  
print $zahl3," = ",int($zahl3),"<br>";

Die Ausgabe lautet:

1024 = 1024
10.25 = 10
-20.2 = -20

# Absoluter Zahlenwert

Die Funktion abs ermittelt den absoluten Wert einer Zahl.

integer abs(integer);

Ein Beispiel:

my $abs1 = -1024;  
my $abs2 = -5.5;  
print $abs1," = ",abs($abs1),"<br>";  
print $abs2," = ",abs($abs2),"<br>";

Die Ausgabe des Beispiels lautet:

–1024 = 1024
-5.5 = 5.5

Diese Funktion konvertiert im Endeffekt alle negativen Zahlen in positive.

# Zusammenfassung

  • Die Standardfunktionen in Perl unterteilen sich in fünf Kategorien: Zeichenkettenfunktionen, Hash- und Listenfunktionen, Datums- und Zeitfunktionen, mathematische Funktionen und Umwandlungsfunktionen.
  • Diese Funktionen werden bei alltäglichen Programmieraufgaben das eine oder andere Mal benötigt.

# Fragen und Übungen

  1. Was bewirken die Funktionen lc und uc?
  2. Schreiben Sie ein Perl-Script, das ermittelt, wie oft der Buchstabe »e« in einer Zeichenkette vorkommt.
  3. Schreiben Sie ein Perl-Script, das das aktuelle Datum nach lokaler Zeitzone in der Form »Wochentag, Tag.Monat.Jahr« ausgibt. Sowohl der Tag und der Monat als auch das Jahr sollen als Zahl ausgegeben werden.
  4. Schreiben Sie ein Perl-Script, das von 49 Zahlen sechs jeweils unterschiedliche Zahlen errechnet (Lotto-Zahlziehung).