SELFHTML: CGI/Perl / Perl-Sprachelemente / Zeichenketten und Listen manipulieren
Description: (SELFHTML 7.0) Wie Sie in Perl Zeichenketten durchsuchen, ändern oder Elemente in Listen löschen, sortieren oder einfügen.
Keywords: SELFHTML, Perl, Zeichenketten, Listen, Anhängen, Einfügen, Löschen, Sortieren

SELFHTML/Quickbar CGI/Perl Perl-Sprachelemente

| ## Zeichenketten und Listen manipulieren
| Teile aus Zeichenketten extrahieren Zeichenketten in Listen verwandeln Listenelemente zu Zeichenkette verbinden Listenelemente hinzufügen, ersetzen und löschen Listenelemente sortieren Suchen und Ersetzen von Zeichen oder Zeichenketten

## Teile aus Zeichenketten extrahieren

Sie können aus einer größeren Zeichenkette ein einzelnes Zeichen oder eine Zeichenfolge entnehmen.

### Beispiel:

    #!/usr/bin/perl

    $Url = "http://www.teamone.de/selfhtml/tgck.htm";

    $Stop = index($Url,":");
    $Protokoll = substr($Url,0,$Stop);
    $Start = index($Url,"//") + 2;
    $Domain = substr($Url,$Start);
    $Stop = index($Domain,"/");
    $Domain = substr($Domain,0,$Stop);
    $Start = rindex($Url,"/") + 1;
    $Dateiname = substr($Url,$Start);
    $Url_Laenge = length($Url);

    print "Das verwendete Internet-Protokoll der URL-Adresse lautet: ", $Protokoll, "\n";
    print "Die Domain-Adresse der URL-Adresse lautet: ", $Domain, "\n";
    print "Der Dateiname der URL-Adresse lautet: ", $Dateiname, "\n";
    print "Die URL-Adresse hat eine Laenge von: ", $Url_Laenge, " Zeichen\n";

### Erläuterung:

Im obigen Beispiel wird aus einer URL-Adresse, die in dem Skalar `$Url` gespeichert wird, das Internet-Protokoll (im Beispiel: http), die Domain-Adresse (im Beispiel: www.teamone.de) und der Dateiname (im Beispiel teck.htm) extrahiert. Alle drei Teile der URL-Adresse werden in eigenen Skalaren gespeichert. Das Internet-Protokoll wird in `$Protokoll` gespeichert, die Domain-Adresse in `$Domain` und der Dateiname in `$Dateiname`. Am Ende des Scripts werden die ermittelten Teile mit der `print`-Funktion ausgegeben.

Die Perl-Funktion, mit deren Hilfe Sie eine Teilzeichenkette aus einer größeren Zeichenkette extrahieren können, heißt `substr` (= Unterzeichenkette). Diese Funktion erwartet zwei oder drei Parameter. Der erste Parameter ist die Zeichenkette, von der ein Teil extrahiert werden soll. Der zweite Parameter ist eine Zahl. Die Zahl gibt an, ab dem wievielten Zeichen der Zeichenkette die Teilzeichenkette extrahiert werden soll. Dabei wird bei 0 (für das erste Zeichen) zu zählen begonnen. Wenn Sie beispielsweise `substr(Stefan,2)` notieren, gibt die Funktion `efan` zurück. Als dritten Parameter können Sie `substr` noch mitteilen, wieviele Zeichen ab dem angegebgenen Startzeichen extrahiert werden sollen. Wenn Sie etwa `substr(Stefan,2,3)` notieren, erhalten Sie als Ergebnis `efa`.

Häufig wissen Sie jedoch nicht, an der wievielten Stelle einer Zeichenkette ein gewünschter, sinnvoller Teil beginnt. Dafür wissen Sie, daß die Zeichenkette einen bestimmten Aufbau hat. So ist es auch im obigen Beispiel. Die Zeichenkette stellt eine URL-Adresse dar. URL-Adressen haben bekanntlich einen einheitlichen Aufbau. Wenn Sie, wie im Beispiel, etwa die Domainadresse aus einer URL extrahieren wollen, wissen Sie, daß die Domainadresse hinter dem doppelten Schrägstrich // beginnt. Perl bietet dazu die Funktionen `index` und `rindex` an. Mit `index` ermitteln Sie, an der wievielten Stelle einer Zeichenkette ein bestimmtes Zeichen oder eine bestimmte Zeichenfolge zum `nächsten mal` vorkommt. Mit `rindex` ermitteln Sie, an der wievielten Stelle einer Zeichenkette ein bestimmtes Zeichen oder eine bestimmte Zeichenfolge zum `letzten mal` vorkommt. Beide Funktionen erwarten zwei Parameter. Als ersten Parameter übergeben Sie die Zeichenkette, in der nach dem Vorkommen eines Zeichens oder einer Zeichenfolge gesucht werden soll. Als zweiten Parameter bekommt die Funktion das Zeichen oder die Zeichenfolge übergeben, nach der gesucht werden soll. Beide Funktionen geben dann eine Zahl zurück. Diese Zahl können Sie dann in `substr` als zweiten Parameter übergeben. Wenn Sie beispielsweise `index("Opa nahm Opium","Op")` notieren, erhalten Sie 0 zurück, weil "Op" gleich am Anfang zum ersten mal vorkommt. Wenn Sie dagegen `rindex("Opa nahm Opium","Op")` notieren, erhalten Sie 9 zurück, da in diesem Fall das letzte Vorkommen von "Op" ermittelt wird.

Es ist sinnvoll, die Rückgabewerte der all dieser Perl-Funktionen in eigens dafür definierten Skalaren zu speichern, so wie im obigen Beispiel. Diese Skalare können Sie anschließend bequem weiterverarbeiten.

### Beachten Sie:

Eine weitere interesante Funktion für Zeichenketten ist `length` (siehe Beispiel). Diese Funktion gibt die Anzahl Zeichen in einer Zeichenkette zurück.

## Zeichenketten in Listen verwandeln

Wenn Sie Zeichenketten haben, die bestimmte, regelmäßig vorkommende Zeichen enthalten, können Sie diese Zeichen als Trennzeichen behandeln und die Zeichenkette in eine Liste übertragen.

### Beispiel:

    $CSV_Zeile = "Wilhemine Sauerapfel,Schlundstr. 13,90001 Neunhausen,099/12345";
    @Adresse = split(/,/,$CSV_Zeile,4);
    $i = 0;
    for(@Adresse)
     {
      print $i+1, ". Feld der Adresse: ", $Adresse[$i], "\n";
      $i++;
     }

### Erläuterung:

Im obigen Beispiel ist in dem Skalar `$CSV_Zeile` eine typische Zeile aus einer kommabegrenzten Datei gespeichert. Viele Datenbank- und Tabellenkalkulationsprogramme bieten die Möglichkeit, strukturierte Daten in Form solcher kommabegrenzter Dateien abzuspeichern. Dateien dieser Art werden üblicherweise mit der Dateiendung `.csv` abgespeichert. Wenn Sie so eine Datei zeilenweise einlesen, erhalten Sie in jeder Zeile einen Inhalt von der Art, wie er im obigen Beispiel in `$CSV_Zeile` gespeichert ist.

Mit der Perl-Funktion `split` können Sie solche Inhalte in Felder aufteilen und in einer Liste speichern. Definieren Sie eine Liste wie im Beispiel die Liste `@Adresse`. Dieser Liste weisen Sie den Rückgabewert von `split` zu. Die Funktion `split` erwartet zwei, optional auch drei Parameter. Als ersten Parameter übergeben Sie einen regulären Ausdruck, mit dessen Hilfe der Feldtrenner ermittelt wird. Im obigen Beispiel ist das einfach das Kommazeichen. Als zweiten Parameter übergeben Sie die Zeichenkette, aus der die Liste erzeugt werden soll. Im Beispiel ist das der Skalar `$CSV_Zeile`. Als dritten Parameter können Sie der `split`-Funktion noch angeben, wie viele Felder sie maximal erzeugen soll. Im obigen Beispiel ist das eigentlich nicht nötig, aber der Vollständigkeit halber wird 4 übergeben, denn so viele Datenfelder enthält die Adressenzeile.

## Listenelemente zu Zeichenkette verbinden

Sie können aus Elementen einer Liste eine Zeichenkette bilden.

### Beispiel:

    #!/usr/bin/perl

    @Adresse = ("Wilhemine Sauerapfel","Schlundstr. 13","90001 Neunhausen","099/12345");
    $CSV_Zeile = join(",",@Adresse);
    print "Die erzeugte Zeichenkette lautet: ", $CSV_Zeile, "\n";

### Erläuterung:

Im obigen Beispiel haben Sie eine Adresse in einer Liste `@Adresse` mit Feldern für die einzelnen Daten gespeichert. Diese Liste können Sie mit Hilfe der Perl-Funktion `join` in eine Zeichenkette verwandeln. Dabei geben Sie außerdem an, durch welches Zeichen oder welche Zeichenfolge die Felder in der zu erzeugenden Zeichenkette voneinander getrennt werden sollen. Die Funktion `join` ist also die Umkehrfunktion zu `split`.

Definieren Sie einen Skalar wie im Beispiel den Skalar `$CSV_Zeile`. Diesem Skalar weisen Sie den Rückgabewert von `join` zu. Die Funktion `join` erwartet zwei Parameter. Als ersten Parameter übergeben Sie das Zeichen oder die Zeichenfolge, durch die die Felder in der zu erzeugenden Zeichenkette voneinander getrennt sein sollen. Im Beispiel ist das einfach ein Kommazeichen. Als zweiten Parameter übergeben Sie die Liste, aus der die Zeichenkette erzeugt werden soll. Im Beispiel ist das die Liste `@Adresse`.

## Listenelemente hinzufügen, ersetzen und löschen

Eine Liste muß keinen festen Inhalt und keine feste Länge haben. Sie können beispielsweise während des Programmlaufs zu einer Liste Elemente an eine Liste anhängen oder Elemente aus der Liste löschen.

### Beispiel 1: Element hinzufügen:

    #!/usr/bin/perl

    @Adresse = ("Wilhemine Sauerapfel","Schlundstr. 13","90001 Neunhausen","099/12345");
    push(@Adresse,"sauerapfel\@finster.de");
    for(@Adresse)
     {
      print $_, "\n";
     }

### Beispiel 2: Element entfernen

    #!/usr/bin/perl

    @Adresse = ("Wilhemine Sauerapfel","Schlundstr. 13","90001 Neunhausen","099/12345");
    pop(@Adresse);
    for(@Adresse)
     {
      print $_, "\n";
     }

### Beispiel 3: Element ersetzen

    #!/usr/bin/perl

    @Adresse = ("Wilhemine Sauerapfel","Schlundstr. 13","90001 Neunhausen","099/12345");
    $Adresse[1] = "Hasenschartenstr. 7";
    for(@Adresse)
     {
      print $_, "\n";
     }

### Beispiel 4: Elemente umsortieren

    #!/usr/bin/perl

    @Adresse = ("Wilhemine Sauerapfel","Schlundstr. 13","90001 Neunhausen","099/12345");
    for($i=1;$i<3;$i++)
     {
      $Temp = shift(@Adresse);
      push(@Adresse,$Temp);
     }
    for(@Adresse)
     {
      print $_, "\n";
     }

### Erläuterung:

Mit Hilfe der Perl-Funktion `push` können Sie ein Element an eine Liste anhängen. Im obigen Beispiel 1 wird an die Liste `@Adresse` ein Element angehängt, das eine E-Mail-Adresse enthält. Die Funktion `push` bekommt beim Aufruf im ersten Parameter die Liste übergeben, an die Sie ein oder mehrere Elemente anhängen möchten. Dahinter geben Sie ein oder mehrere Elemente an, die Sie anhängen möchten. Das können Zeichenketten oder Zahlen sein. Im obigen Beispiel wird nur ein Element angehängt, nämlich die E-Mail-Adresse. Wenn Sie mehrere Elemente anhängen wollen, trennen Sie diese durch Kommata.
Der Schrägstrich in der E-Mail-Adresse gehört übrigens nicht zu der Adresse, sondern ist ein Maskierungszeichen für das Klammeraffenzeichen @, da dieses Zeichen in Perl eine eigene Bedeutung hat (es markiert Listen).

Mit Hilfe der Funktion `pop` können Sie das letzte Element einer Liste entfernen. Dazu übergeben Sie beim Aufruf der Funktion einfach die Liste, deren letztes Element Sie entfernen wollen. Im obigen Beispiel 2 ist das die Liste `@Adresse`. In dem Beispiel wird die Telefonnummer aus der Liste entfernt.

Um in einer Liste ein bestimmtes Element zu ersetzen, sprechen Sie einfach das betreffende Listenelement an und weisen ihm einen anderen Wert zu, so wie im obigen Beispiel 3.

Das obige Beispiel 4 zeigt, wie Sie die Elemente einer Liste "händisch" umsortieren können. Dazu eignet sich die Perl-Funktion `shift`. Diese Funktion entfernt das erste Element aus einer Liste und gibt es zurück. Alle weiteren Elemente rücken eins nach vorne, so daß das bislang zweite Element nun das erste wird usw. Damit das entfernte erste Element nicht verloren geht, können Sie es in einem Skalar zwischenspeichern. Im obigen Beispiel 4 wird das entfernte Element im Skalar `$Temp` zwischengespeichert. Mit der Funktion `push` wird dieses Element anschließend wieder ans Ende der Liste angehängt. Im Beispiel findet dieser Austausch innerhalb einer for-Schleife statt. Auf diese Weise lassen sich mehrere Elemente nacheinander umsortieren. In dem Beispiel stehen am Ende Ort und Telefonnummer der Adresse am Anfang der Liste, gefolgt von Name und Straße.

## Listenelemente sortieren

Eine sehr leistungsstarke Funktion in Perl ist die Möglichkeit, Listen zu sortieren.

### Beispiel 1: Zeichenketten sortieren

    #!/usr/bin/perl

    @Freundinnen = ("Nina","Martina","Annina","Christina","Ina","Sabrina");
    @Ordnung = sort(@Freundinnen);
    for(@Ordnung)
     {
      print $_, "\n";
     }

### Beispiel 2: Zahlen sortieren

    #!/usr/bin/perl

    @HighscoreListe = (9834,9837,5989,4509,4329,6509,2837,8289,10845);
    @SortierteListe = sort NummernSort @HighscoreListe;
    @AbsteigendSortierteListe = reverse @SortierteListe;
    for(@AbsteigendSortierteListe)
     {
      print $_, "\n";
     }

    sub NummernSort
    {
     if($a < $b)
      { return -1; }
     elsif($a == $b)
      { return 0; }
     else
      { return 1; }
    }

### Erläuterung:

Zum automatischen Sortierung von Listen steht die Perl-Funktion `sort` zur Verfügung. Diese Funktion sortiert die Elemente einer Liste, die der Funktion als Parameter übergeben wird, automatisch alphabetisch in aufsteigender Reihenfolge. Wenn Sie genau das erreichen wollen, brauchen Sie nur einen Befehl wie im obigen Beispiel 1 der Befehl `@Ordnung = sort(@Freundinnen)`. In diesem Beispiel wird die Liste `@Freundinnen` sortiert. Die sortierte Liste wird in `@Ordnung` gespeichert.

Schwieriger wird es, wenn Sie numerische Werte sortieren wollen, so wie im obigen Beispiel 2. Dazu brauchen Sie ein eigenes Unterprogramm, das ein bestimmtes Aussehen haben muß, da die `sort`-Funktion dieses Unterprogramm auf Wunsch aufruft. Das Unterprogramm `NummernSort` aus Beispiel 2 können Sie für all solche Zwecke verwenden. Mit der Anweisung `@SortierteListe = sort NummernSort @HighscoreListe;` wird im Beispiel die Liste `@HighscroreListe` numerisch sortiert. Lassen Sie bei diesem Funktionsaufruf am besten die Klammern weg und notieren Sie hinter `sort` den Namen des Unterprogramms für den Sortiervorgang, im Beispiel also `NummernSort`. Dahinter folgt die Angabe der Liste, die auf diese Weise sortiert werden soll, im Beispiel `@HighscoreListe`.

Wenn Sie eine Liste nicht aufsteigend, sondern absteigend sortiert haben wollen, können Sie die Perl-Funktion `reverse` anwenden. Im obigen Beispiel 2 wird die Liste `@SortierteListe`, die zunächst aufsteigend sortiert ist, mit der Anweisung `@AbsteigendSortierteListe = reverse @SortierteListe;` in eine neue Liste mit dem Namen `@AbsteigendSortierteListe` gespeichert. Diese Liste ist absteigend sortiert.

## Suchen und Ersetzen von Zeichen oder Zeichenketten

Das mächtige Werkzeug der regulären Ausdrücke wird in Perl auch oft dazu benutzt, um in Zeichenketten bestimmte Zeichen oder Zeichenfolgen durch andere zu ersetzen, oder um bestimmte Zeichen oder Zeichenfolgen aus Zeichenketten zu entfernen. Dazu gibt es eine spezielle Syntax.

### Beispiel 1: Alle Buchstaben und Leerzeichen entfernen

    #!/usr/bin/perl

    $Text = "Franz jagt im komplett verwahrlosten Taxi quer durch Bayern 1234567890";
    $Text =~ s/[a-z]| //gi;
    print $Text;

### Beispiel 2: Deutsche Umlaute HTML-gerecht ersetzen

    #!/usr/bin/perl

    $Text = "In München steht ein Hofbräuhaus, dort gibt es Bier in Maßen";
    $Text =~ s/ä/\&auml\;/g;
    $Text =~ s/ö/\&ouml\;/g;
    $Text =~ s/ü/\&uuml\;/g;
    $Text =~ s/Ä/\&Auml\;/g;
    $Text =~ s/Ö/\&Ouml\;/g;
    $Text =~ s/Ü/\&Uuml\;/g;
    $Text =~ s/ß/\&szlig\;/g;
    print $Text;

### Beispiel 3: Fehlerhafte Angaben entfernen und unterdrücken

    #!/usr/bin/perl

    @Schulnoten = (1,4,7,2,X,3,0,1,6,3,3,8,R,G,9,2,3,4,1,1,3);
    $Notenkette = join(",",@Schulnoten);
    $Notenkette =~ s/[7-9]|0|[A-Z]//gi;
    @NeueNoten = split(/,|,,/,$Notenkette);
    for(@NeueNoten)
     {
      unless($_ eq "")
       {
        print $_, "\n";
       }
     }

### Erläuterung:

Das Schema für alle Suche-Ersetze-Vorgänge in Perl lautet:
`Zeichenkette =~ s/Suchmuster/Ersetzmuster/[Optionen]`

`Zeichenkette` ist meistens ein Skalar, in dem eine Zeichenkette gespeichert ist, so wie etwa `$Text` im obigen Beispiel 1. Dahinter notieren Sie die Zuweisung `=~`, gefolgt von einem Leerzeichen und dem kleinen Buchstaben `s`. Unmittelbar hinter dem kleinen `s` folgt ein regulärer Ausdruck, markiert durch die Schrägstriche `/.../`. In diesem Suchausdruck definieren Sie nach den Regeln für reguläre Ausdrücke, wonach in der Zeichenkette gesucht werden soll. Hinter dem abschließenden Schrägstrich folgt ein zweiter Ausdruck. In diesem Ausdruck notieren Sie das Zeichen oder die Zeichenfolge, durch die Fundstellen ersetzt werden sollen. Dahinter folgt nochmals ein abschließender Schrägstrich. Hinter diesem Schrägstrich können Sie mit Hilfe von erlaubten Kleinbuchstaben Optionen für den Suche-Ersetze-Vorgang definieren. Dabei sind folgende Buchstaben wichtig:
`g` sucht/ersetzt alle Fundstellen (ansonsten wird nur die erste Fundstelle ersetzt)
`i` sucht/ersetzt Buchstaben unabhängig davon, ob sie groß oder klein geschrieben sind (ansonsten wird Groß-/Kleinschreibung unterschieden)

Im obigen Beispiel 1 werden aus `$Text` alle Buchstaben (groß und klein) und alle Leerzeichen entfernt. Es bleiben anschließend also nur noch die Ziffern am Ende stehen.

Im obigen Beispiel 2 werden in `$Text` alle deutschen Umlaute und scharfes S durch ihre HTML-gerechten Umschreibungen ersetzt.

Im obigen Beispiel 3 werden aus der Liste `@Schulnoten` alle Werte entfernt, die nicht zwischen 1 und 6 liegen. Dazu wird die Liste zu einer Zeichenkette verbunden. Aus dieser Zeichenkette `$Notenkette` werden alle Ziffern entfernt, die nicht zwischen 1 und 6 liegen, sowie alle Buchstaben. Das Ersetzmuster bleibt dabei leer, was dazu führt, das die Fundstellen einfach entfernt werden. Anschließend wird die behandelte Zeichenkette in eine Liste verwandelt. Dabei werden mit dem regulären Ausdruck `/,|,,/` auch alle leeren Elemente, die der Suche-Ersetze-Vorgang zurückgelassen hat, übergangen. Die neue Liste enthält nur noch gültige Schulnoten zwischen 1 und 6.

weiter: | Mit Zahlen und Zeit arbeiten
zurück: | Dateien lesen und schreiben

SELFHTML/Quickbar CGI/Perl Perl-Sprachelemente

© 1998 Stefan Münz, muenz@csi.com