Sehr Umfangreiche Webseite zum Programmieren in C Perl CGI, Skripting, Konvertieren, int ceil sprintf hex oct floor Runden AbschneidenPerl Kurs Skripting Arrays Zeichenketten split map join unmap shift unshift splice $_ Zahlen-Array continue Arrays Zeichenketten split map join unmap shift unshift splice $_ Zahlen-Array Perl Kurs Kapitel 8

8.1. Der Bereichsoperator .. und die Standardvariable $_           zurück Ein Kapitel tiefer zum Inhaltsverzeichnis

Den Bereichsoperator haben Sie bereits einmal kurz bei der foreach-Schleife kennen gelernt. Diesen können Sie verwenden, um z.B. anstatt  zu schreiben ...

1,2,3,4,5,6,7,8,9,10,11,12

... mit dem Bereichsoperator  ...

1..12

Dies stellt ein verkürzte Schreibweise der Zahlen 1 bis 12 da. Natürlich ist dies auch mit Zeichen möglich ...

a..z

Hier werden die Zeichen a bis z festgelegt.

Der Bereichsoperator funktioniert übrigens nur, wenn das linke Argument kleiner oder gleich dem rechten Argument ist. Folglich wäre folgende Angabe falsch ...

@array = 100 .. 0;

Die Variable $_ ist eine von Perl vordefinierte skalare Standardvariable die Sie noch in vielen der folgenden Kapitel begegnen werden. Ein kurzes Beispiel hierzu ...

#!/usr/bin/perl -w

foreach $zahl (1..10)
 {
   print $zahl , "\n";
 }

Hiermit wird die Zahl 1 bis 10 auf dem Bildschirm ausgegeben. Jetzt machen nochmals dasselbe Beispiel mit der Standardvariable $_  ...

#!/usr/bin/perl -w

foreach (1..10)
 {
   print $_ , "\n";
 }

Hiermit wird wieder der Wert 1 bis 10 auf den Bildschirm ausgegeben. Wie das? Nun da keine Variable nach der foreach-Schleife definiert wurde, wird automatisch jedes Listenelement in die Standardvariable $_ kopiert.

Keine Sorge Sie werden dem Bereichsoperator und der Standardvariablen noch recht häufig begegnen.

8.2. Zahlen Arrays           zurück Ein Kapitel tiefer Ein Kapitel höher zum Inhaltsverzeichnis

Nachdem Sie sich bisher nur mit den skalaren Variablen beschäftigt haben, kommen Sie nun zu den Arrays.  Nach diesem Kapitel werden wohl die letzten Zweifel beseitigt sein, dass Perl unumstritten die beste Programmiersprache darstellt wenn es um Textverarbeitung geht. Gerade Programmierer die in C/C++ programmieren werden einige Verständnisprobleme bekommen. Warum? Weil es oftmals zu einfach ist ;) Wo man in anderen Sprache eigene Routinen schreiben muss, geht dies in Perl häufig mit gerade mal einer Zeile. Selbst ich musste zu Beginn manche Abschnitte zweimal Lesen weil ich es mir nicht vorstellen konnte das es so simpel ist.

Nun als erstes zu den Arrays von Zahlen. C-Programmierer definieren die Werte eines Arrays etwas so ...

int werte[10] = { 1,2,3,4,5,6,7,8,9,10 };

Anmerkung für Anfänger : Computer beginnen bei 0 zu zählen, da der Wert 0 für den Computer ebenso ein Darstellbarer Wert ist.

In Perl hat die Definition eines Arrays mit Zahlen folgendes Aussehen ...

@werte = (1,2,3,4,5,6,7,8,9,10);

Natürlich kann man diese Schreibweise auch mit dem Bereichsoperator abkürzen ...

@wert = (1..10);

Dies entspricht der selben Wertdefinition wie zuvor. Ein Array erkennen Sie also an dem Präfix @ vor dem Variablennamen.

Als erstes werden Sie die einzelnen Werte der Liste durchlaufen. Wenn Sie einen einzelnen Wert in einem Array verwenden wollen, benötigen Sie einen Index (oder auch Feldindex genannt), der auch bei Perl in eckige Klammern geschrieben wird. Außerdem muss, wenn man ein einzelnes Element der Liste ausgeben will, das Präfix $ für Skalar an den Array-Namen hinzugefügt werden. Hierzu nun ein Beispiel ...

#!/usr/bin/perl -w

@werte = (1..20);

print "Es werden alle geraden Zahlen zwischen 1 und 20 ausgegeben\n";

for($i=1; $i < 20; $i++)
 {
   if($werte[$i]%2)
     {
       next;
     }
   print $werte[$i] , "\n";
 }

Sie definieren hier ein Array mit den Werten 1-20, durchlaufen eine Schleife von 1-20 und überprüfen, ob die Bedingung von $wert[$i]%2 einen Rest ergibt. Falls ja, wird mit next, wieder an dem Schleifenanfang gesprungen. Falls kein Rest herauskommt, ist es eine gerade Zahl und Sie geben die Zahl aus.

Also nochmals, wenn Sie auf eine einzelnes Element in einem Array zugreifen wollen müssen Sie das Präfix $ für Skalar verwenden und den Indexwert in eckigen Klammern.

Das ganze kann man natürlich auch mit der Standardvariable $_ bewältigen ...

#!/usr/bin/perl -w

@werte = (1..20);

print "Es werden alle geraden Zahlen zwischen 1 und 20 ausgegeben\n";

foreach (@werte)      #Das Array @werte wird durchlaufen
 {
   if($_%2)            #Gerade Zahl?
     {
       next;           #Nein
     }
   print $_ , "\n";    #Gerade Zahl ausgeben
 }

Nun kennen Sie eine Möglichkeit, wie Sie Array durchlaufen und auf einzelnen Elemente zugreifen können. Wie kann man aber nun herausfinden, wie viele Werte sich tatsächlich in diesem Array befinden? Sie werden überrascht sein ...

#!/usr/bin/perl -w

@werte = (11, 48, 23, 10, 33, 66);

$anzahl_werte = @werte;

print "\n", $anzahl_werte , "\n";

Und hierbei bekommen Sie den Wert 6 zurück. Eine Weitere Möglichkeit stellt diese Möglichkeit da ...

#!/usr/bin/perl -w

@werte = (11, 48, 23, 10, 33, 66);

print "\n", $#werte+1 , "\n"; # $#werte stellt den Index des letzten Wertes da
print $werte[$#werte], "\n";  # Hier der Beweis

Was sagt uns das nun wieder? Der höchste Index eines Array wird in der Variablen $#werte festgehalten, was uns die Ausgabe mittels ...

print $werte[$#werte], "\n";

... auch beweist. Jetzt dürfte wohl auch klar sein wieso ...

$anzahl_werte = @werte;

... die Anzahl der Elemente in dem Array zurückgibt. Intern kann man sich dies dann so vorstellen ...

$anzahl_werte = $#werte+1;

8.3. Funktion map           zurück Ein Kapitel tiefer Ein Kapitel höher zum Inhaltsverzeichnis

Mit der Funktion map haben Sie eine weitere komfortable Möglichkeit, Arrays zu durchlaufen und zu bearbeiten. Ein einfaches Beispiel. Sie wollen alle Elemente eines Arrays mit einem bestimmten Wert berechnen. Um map zu verwenden benötigen Sie wiederum die Standardvariable $_, in der unser Wert des Arrays steht, der im Augenblick zu berechnen ist. Doch lassen wir ein Programm sprechen ...

#!/usr/bin/perl -w

@werte = (1..100);
@neuewerte = map {$_ * 2} @werte;
print @neuewerte , "\n";

Hiermit werden alle 100 Werte in @werte verdoppelt und an das neue Array @neuewerte übergeben. Was im Prinzip schwierig aussieht, verkappt sich auch nur als eine Einfache foreach-Schleife. Nur anstatt wie in anderen Programmiersprachen erst einmal eine Funktion zu schreiben, muss man in Perl nur noch diese Funktion verwenden. Hier geschieht nichts anderes als das der aktuelle Wert vom Array @wert an die Standartvariable $_ übergeben wird und anschließend wird der Ausdruck in den geschweiften Klammern ausgewertet bzw. hier ausgerechnet und an dem selben Index von @neuewerte übergeben. Danach wird der Index um den Wert 1 erhöht und so weiter.

Hierzu folgt ein Skript eines Währungsumrechner, der eine Preisliste in einen bestimmten Kurs umrechnen soll ...

#!/usr/bin/perl -w

@werte = (1.99, 2.99, 4.99, 10.99);               #Preistabelle
$kurswert=0;

print "Sie können die Preistabelle zu einem bestimmten Kurs ausgeben lassen!\n";
print "Wie lautet der Kurs (Euro/Kurs) : ";
chomp ($kurswert=<STDIN>);

@kurs = map {$_ /$kurswert} @werte;

print "Aktueller Kurs : \n";
printf "%6.2f %6.2f %6.2f %6.2f\n", @werte;

print "Kurs umgerechnet :\n";
printf "%6.2f %6.2f %6.2f %6.2f\n", @kurs;

Im obrigen Beispiel werden Sie schon überrascht gewesen sein, als wir über die simple Ausgabe-Möglichkeit ...

print @neuewerte , "\n";

... den Inhalt des kompletten Arrays @neuewerte ausgaben. Im zweiten Beispiel dürfte Sie (falls Programmiererfahrung) diese Art ...

printf "%6.2f %6.2f %6.2f %6.2f\n", @kurs;

... auch ein wenig überrascht haben. Damit werden wirklich die einzelnen Elemente formatiert ausgegeben.

8.4. Funktionen pop, push, shift, unshift und splice           zurück Ein Kapitel tiefer Ein Kapitel höher zum Inhaltsverzeichnis

Jetzt kommt ein  Thema, was C-Programmierer als dynamisches Array verstehen dürften. Nur das es in Perl ohne umständlich Speicher-Allokationen (calloc, realloc) vor sich geht, sondern mit einfachen Funktionen wie z.B. pop und push.

Mit push können wir ein oder mehrere Elemente an das Ende unseres Arrays hängen. Oder auch ein Array an ein anderes Array hängen ...

#!/usr/bin/perl -w

@werte = (1..10);               #Werte von 1-10
$zahl = 4;
@weitere_werte = (20..30);      #Werte von 20-30

print "Demonstrationsprogramm zu push\n\n";

print "Es sind " . ($#werte+1) . " Elemente in der Liste\n";

push (@werte , 15);             #Wir hängen die Zahl 15 hinten an
print "Nun sind " . ($#werte+1) . " in der Liste\n";

push (@werte, 17, 18, 19);
#Es funktioniert natürlich auch mit mehreren Werten
print "Nun sind es " . ($#werte+1) . "\n";

push (@werte, $zahl);         #So gehts natürlich auch
print "And now there are " . ($#werte+1) . " elements in the list\n";

push (@werte, @weitere_werte); #Jetzt hängen wir ein ganzes Array hinten dran

print "Zum Schluss haben wir folgende " . ($#werte+1) . " in der Liste : \n";
print "@werte" , "\n";

Ich denke mal das Programm ist selbsterklärend. Neu wird für Sie diese Schreibweise gewesen sein ...

print "@werte" , "\n";

Wenn Sie das Array in doppelt Hochkommata stellen, werden die einzelnen Werte des Array mit einem Leerzeichen dazwischen ausgegeben.

Eine weitere Möglichkeit ein Array zu vergrößern haben Sie übrigens mit der Standardvariablen $#name. Der Nachteil ist aber, dass die Werte zu Beginn noch undefiniert sind und Sie diese überprüfen müssen um Fehler zu vermeiden ...

#!/usr/bin/perl -w

@werte = (0);
$#werte = 5;        #Wir vergrössern das Array auf 5 Elemente

foreach (@werte)
 {
   if(defined $_)   #ist defined=definiert oder undefined=undefiniert
     {
        next;
     }
   else
     {
       $_ = 0;
     }
 }
print "@werte" , "\n";

Mit der Funktion pop können Sie das letzte Element eines Array entfernen ...

#!/usr/bin/perl -w

@werte = (1..10); #Werte von 1-10


print "Demonstrationsprogramm zu pop\n\n";

print "Es sind " . ($#werte+1) . " Elemente in der Liste\n";

pop @werte; #Wir entfernen das letzte Element des Arrays
print "Es sind " . ($#werte+1) . " Elemente in der Liste\n";

$delete = pop @werte;
print "Das Element mit dem Wert " . $delete . " wurde aus dem Array entfernt\n";
print "Somit sind noch folgende " . ($#werte+1) . " Werte in dem Array : " . "@werte" . "\n";

Mit der Funktion shift können Sie das erste Element eines Arrays entfernen und mit unshift können Sie eines oder mehrere Elemente an den Anfang eines Arrays hinzufügen ...

#!/usr/bin/perl -w

@werte = (1..10);  #Werte von 1-10
$zahl=99;

print "Demonstrationsprogramm zu shift und unshift\n\n";

print "Es sind " . ($#werte+1) . " Elemente in der Liste\n";
print "@werte" , "\n";

shift @werte;   #Wir entfernen das erste Element des Arrays
print "Es sind " . ($#werte+1) . " Elemente in der Liste\n";
print "@werte" , "\n";

unshift (@werte, 666);   #Wir fügen einen Wert ganz am Anfang hinzu
print "Es sind " . ($#werte+1) . " Elemente in der Liste\n";
print "@werte" , "\n";

unshift (@werte, $zahl, 111, 222);      #Geht auch so
print "Es sind " . ($#werte+1) . " Elemente in der Liste\n";
print "@werte" , "\n"

Eine Verwendung von shift ist häufig in folgender Form zu sehen ...

$arg = shift;

Diese Schreibweise ist nicht zu erraten wenn man Sie nicht kennt. Sie gleichwertig zu ...

$arg = shift @_;

... und somit auch gleichwertig zu ...

$arg = shift @ARGV;

Damit sind Sie in der Lage, die einzelnen Parameter der Kommandozeile auszulesen ...

#!/usr/bin/perl -w

if($arg=shift) { }
else{$arg = "kein Argument";}
if($arg2=shift){ }
else {$arg2 = "kein 2.Argument"; }

print "1.Argument: $arg \n2.Argument: $arg2\n";

Hier ein Beispiel um 2 Argumente aus der Kommandozeile auszulesen. An diesem Programm können erkennen, dass ein weiterer shift-Aufruf das zweite Argument auswertet und so weiter.

So nun kennen Sie einige Möglichkeiten, wie Sie am Anfang und Ende eines Arrays Werte hinzufügen oder entfernen können. Nun fehlt uns noch die Möglichkeit, Sie werden es schon ahnen, Arrays irgendwo aus der Mitte hinzuzufügen bzw. zu entfernen. Und Perl wäre nicht Perl wenn es dazu keine Funktion gäbe.

Mit der Funktion splice haben Sie nun die Möglichkeit zwischen dem Array herumzuspielen. Es gilt nur folgendes : Wenn Sie drei Parameter angeben ...

splice (@array, 10, 2);   #wir löschen $array[10] und $array[11]

... entfernen Sie einen Bereich aus dem Array. Hier wären es die Elemente aus dem Array @array ab dem Index 10, 2 Elemente. Wenn Sie ein neues Element hinzufügen wollen, benötigen Sie einen 4. Parameter der das/die neue(n) Element(e) ersetzt ...

splice (@array, 10 , 2, @neu);

Hiermit werden in dem Array @array 2 Elemente ab der 10. Indexposition, durch die in dem Array @neu stehendenden, ersetzt. Hierzu nun kleines Beispiel ...

#!/usr/bin/perl -w

@werte = (1..10);    #Werte von 1-10
@neu = (66, 99);     #Die neuen Werte
$zahl = 11;

print "@werte" , "\n";

splice(@werte, 4, 2, @neu);  #Wir ersetzen 5 und 6 durch 66 und 99

print "@werte" , "\n";

@ausschneiden = splice (@werte, 2, 5);
print "Wir haben die Werte " . "@ausschneiden" . " ausgeschnitten\n";

print "@werte" , "\n";

splice (@werte, 2, 2, $zahl, 69); #So gehts auch

print "@werte" , "\n";

8.5. Arrays von Zeichenketten           zurück Ein Kapitel tiefer Ein Kapitel höher zum Inhaltsverzeichnis

Jetzt  zu den Arrays und Zeichenketten oder besser Arrays von Zeichenketten. Was versteht ein C-Programmierer darunter?

char *texte[] = {"Hallo", "Wie gehts", "Guten Tag", "Guten Abend"};

Also ein Zeiger auf Arrays. Hier geht's aber um Perl. Also wie sieht's nun in Perl aus ...

@texte = ("Hallo", "Wie gehts", "Guten Tag", "Guten Abend");

Die Ähnlichkeit lässt sich auch hier nicht leugnen. Man merkt Perl schon an, das es in C programmiert wurde. Jetzt zu den Unterschieden von Arrays mit Zeichenketten und Array mit Zahlen. Auch hier gilt für die Anzahl der Elemente in der Liste ...

#!/usr/bin/perl -w

@texte = ("Hallo", "Wie gehts", "Guten Tag", "Guten Abend");
$anzahl=@texte;
printf $anzahl . "\n";
print $#texte+1 . "\n";

Der Zugriff auf die einzelnen Zeichenkette erfolgt auch hier mit Hilfe des Indexes und einer for oder foreach-Schleife. Das mit der direkten Ausgabe des Arrays funktioniert bei Array von Zeichenketten allerdings nicht mehr ...

#!/usr/bin/perl -w

@texte = ("Hallo", "Wie gehts", "Guten Tag", "Guten Abend");
$counter=0;

foreach (@texte)
 {
   print $_ . "\t";                    #1.Variante
   print $texte[$counter] . "\n";      #2.Variante
   $_=$counter++;                      #Indexzaehler erhöhen
 }
print "@texte" , "\n";

Natürlich funktionieren auch die Funktionen pop, push, unshift, shift und slice. Hierzu auch noch eine Demonstration ...

#!/usr/bin/perl -w

@texte = ("Hallo", "Wie gehts", "Guten Tag", "Guten Abend");
@neue_texte = ("neuer Text", "nixsagender Text");
$counter=0;
$eingabe=0;

push(@texte, $neue_texte[0]);  #hängen "neuer Text" hinten an @texte an
shift @texte;                  #Wir entfernen das erste Element in @texte
unshift (@texte, $neue_texte[1]); #an den Anfang von Texte

print "Bitte geben Sie irgendetwas ein : ";
chomp ($eingabe=<STDIN>);

splice (@texte, 2, 1, $eingabe);
#Wir entfernen "Guten Tag" und fügen dafür unsere neue Eingabe ein

foreach (@texte)
 {
    print $_ , "\t";
    $_=$counter++;
 }
 print "\n";

8.6. Funktionen split und join           zurück Ein Kapitel tiefer zum Inhaltsverzeichnis

Die Funktion split ist ähnlich der Funktion strtok in C. Bei dieser Funktion können Sie einen Text in seinen einzelnen Bestandteilen zerlegen. Hierzu benötigen Sie nur ein Trennzeichen ...

split( TRENNZEICHEN , TEXT);

Hierzu die Funktion split in der Praxis. Geben Sie ein paar Wörter  ein und zerlegen diese dann mit split in die einzelne Arrays ...

#!/usr/bin/perl -w

@text=(0);
$input=0;
$counter=0;

print "Bitte machen Sie eine Eingabe : ";
chomp ($input=<STDIN>);

@text = split(" ", $input);
#Zerlegt alle Wörter ab einem Leerzeichen
#und übergibt dieses Wort an @text

foreach(@text)
 {
   print $_ , "\n";
   $_=$counter++;
 }

Viele werden jetzt vermutet haben, dass die Textzerlegung in einer Schleife stattfindet. Das nimmt uns auch hier wieder eine Funktion ab. Natürlich können Sie auch andere Tokens (engl. f. Zeichen) zur Zerlegung eines Textes in einzelnen Arrays verwenden. Im Prinzip können Sie hierbei jedes darstellbare Zeichen verwenden.

Die Funktion join ist so etwas wie das Gegenstück der Funktion split. Mit dieser Funktion können Sie aus Listen wieder Texte machen.

#!/usr/bin/perl -w

@text=("Name", "Alter", "Wohnort", "Hobbys");
$text_ausgabe=0;

#Übergibt die einzelnen Elemente von @text an $text_ausgabe
$text_ausgabe= join("*", @text);

print $text_ausgabe , "\n";

Somit haben Sie eine alternative für ...

print @text;

... da dies ja nicht mit Zeichenketten von Arrays funktioniert. Also ...

print join (" ",@text);

Das zweite Argument stellt das Trennzeichen da, was zwischen 2 Elementen stehen soll.

Hierzu noch ein etwas nützlicheres Programm. Mit Hilfe der Funktion rand (Pseudo-Zufallsgenerator), join und map werden Sie ein 8 stelliges Passwort erstellen lassen. Sie können das Beispiel in ähnlicher Form ja später als CGI-Skript in Ihre Homepage einbauen ...

#!/usr/bin/perl -w

@zeichen = ('A'..'Z', 'a' .. 'z', 0 .. 9);
$passwort = join("", @zeichen[map{rand @zeichen}(1 .. 8)]);

print "Ihr Passwort : $passwort\n";