Der Split-Operator

(Auszug aus "Reguläre Ausdrücke" von Jeffrey E. F. Friedl)

Die vielseitige Split-Funktion (oft werden Operatoren in Perl etwas ungenau Funktionen genannt) wird meist als Gegenstück zu einem m/.../g im Listenkontext verwendet (siehe Alle Treffer herauspflücken – Listenkontext mit dem /g-Modifikator). Letzterer gibt die Textstücke zurück, auf die die Regex gepasst hat; mit einem split mit der gleichen Regex erhält man die Textstücke dazwischen. Eine Mustersuche mit $Text =~ m/:/g und dem Suchtext ›IO.SYS:225558:95-10-03:-a-sh:optional‹ ergibt eine ziemlich uninteressante Liste mit vier Elementen:

(':', ':', ':', ':')

Ein split(/:/, $Text) dagegen liefert diese Liste mit fünf Elementen:

('IO.SYS', '225558', '95-10-03', '-a-sh', 'optional')

Aus beiden Beispielen wird ersichtlich, dass die Regex ˹:˼ viermal gepasst hat. Bei split wird eine Kopie des Suchtextes an diesen vier Stellen auseinandergeschnitten, und die fünf Bruchstücke werden als Substrings zurückgegeben.

Bei diesem Beispiel wird als Trennzeichen ein einzelnes Zeichen verwendet, aber man kann dafür einen beliebigen regulären Ausdruck nehmen. Bei

@Paragraphen = split(m/\s*<p>\s*/i, $html);

zum Beispiel wird der HTML-Text bei jedem <p> oder <P> inklusive dem Whitespace davor und danach aufgeteilt.

Man kann auch bei Positionen splitten. In diesem Beispiel werden die logischen Zeilen in einem String in »echte« Zeilen aufgeteilt:

@Zeilen = split(m/^/m, $zeilen);

In seiner einfachsten Form und mit einfachen Daten wie den bisher gezeigten ist split leicht verständlich und sehr nützlich. Es gibt aber eine Menge von Optionen, Spezialfällen und besonderen Situationen, die die Sache komplizieren. Bevor wir uns mit diesen komplexeren Anwendungen beschäftigen, möchte ich noch zwei besonders einfache Fälle zeigen:

  • Mit dem besonderen Match-Operanden // wird der String in einzelne Zeichen zerlegt. Mit split(//, "Kleiner Test") erhält man also eine Liste mit zwölf Elementen: ("K", "l", "e", ... "s", "t").
  • Mit dem speziellen Match-Operanden "" (ein normaler String, der nur aus einem einzigen Leerzeichen besteht) wird bei Whitespace aufgeteilt, ganz ähnlich wie mit m/\s+/, aber hier wird Whitespace am Anfang und am Ende des Strings ignoriert.

    Zum Beispiel ergibt split("", "KrautundRüben") eine Liste mit den drei Elementen ›Kraut‹, ›und‹ und ›Rüben‹.

Diese und andere Spezialfälle werden etwas später genauer erläutert, in den nächsten Abschnitten geht es um einfachere Dinge.

Grundlegendes zu split

Der Split-Operator hat bis zu drei Operanden und sieht wie eine Funktion aus:

split(Match-Operand, Suchtext, Limit)

Die Klammern sind fakultativ. Für alle Operanden gibt es voreingestellte Werte.

split wird immer in einem Listenkontext benutzt, meist in der Art wie in diesen Beispielen:

($var1, $var2, $var3, ... ) = split(...);

@array = split(...);

for my $item (split(...)) {
   .
   . 
   .
}

Die einfache Form des Match-Operanden

Für den Match-Operanden gibt es diverse Spezialfälle, aber im Allgemeinen ist es der gleiche Operand wie die Regex beim Match-Operator. Man kann also /.../ oder m{...} und Ähnliches verwenden oder ein Regex-Objekt oder letztlich irgendeinen String-Ausdruck. Nur die fünf allgemeinen Modifikatoren sind jedoch zulässig (siehe Regex-Modifikatoren).

Wenn Sie Klammern zum Gruppieren benötigen, sollten Sie die nicht-einfangenden Klammern ˹(?:...)˼ nehmen. Auf den nächsten Seiten werden wir lernen, dass mit einfangenden Klammern ein Spezialfall aktiviert wird.

Der Suchtext-Operand

Der Suchtext wird von split nur abgesucht, aber nie verändert. Wenn kein Suchtext angegeben ist, wird der Standardsuchtext $_ benutzt.

Einfache Formen des Limit-Operanden

In seiner wichtigsten Funktion setzt der dritte Operand ein oberes Limit für die Anzahl der verlangten Bruchstücke. Bei unseren Beispieldaten würde split(/:/, $Text, 3) folgende Liste zurückgeben:

('IO.SYS', '225558', '95-10-03:-a-sh:optional')

Das zeigt, dass split nach zwei gefundenen Treffern für /:/ aufhört und drei Elemente zurückgibt. Die Regex hätte vielleicht ein weiteres Mal gepasst, aber das ist irrelevant, weil eine obere Grenze angegeben wurde. Es handelt sich nur um eine obere Grenze: Wenn aus den Daten weniger Bruchstücke entstehen, als im Limit-Operanden angegeben, wird nicht etwa mit Leerstrings aufgefüllt. split(/:/, $Text, 99) ergibt also nur fünf Bruchstücke. Trotzdem besteht zwischen split(/:/, $Text) und split(/:/, $Text, 99) ein Unterschied, der hier allerdings nicht in Erscheinung tritt und erst später behandelt wird.

Das angegebene Limit bezieht sich auf die Anzahl der Bruchstücke. Bei drei Treffern wäre im obigen Beispiel als Resultat

('IO.SYS', '225558', '95-10-03', '-a-sh:optional')

herausgekommen; das ist genau nicht, was passiert.

Eine Überlegung zur Effizienz: Nehmen wir an, Sie wollen nur die ersten drei Felder der Zeile erhalten:

($dateiname, $groesse, $datum) = split(/:/, $text)

Perl hört hier von selbst nach drei Feldern auf. Es setzt von selbst ein Limit auf eins mehr als die Anzahl der geforderten Felder.

Komplexes Splitting

Der Umgang mit split ist meist sehr einfach, wie Sie das bei den bisherigen Beispielen gesehen haben. Es gibt aber drei Umstände, die in der Praxis dazwischenfunken:

  • split kann leere Elemente zurückgeben
  • Spezielle Formen des Regex-Operanden bei split
  • Der Regex-Operand mit einfangenden Klammern

Diese Spezialfälle werden in den nächsten Abschnitten näher erläutert.

split kann leere Elemente zurückgeben

Grundsätzlich liefert split Textstücke zwischen Treffern. Wenn zwei Treffer aufeinanderfolgen, wird das »Garnichts« dazwischen als Element zurückgegeben: als leerer String "". Bei

@nums = split(m/:/, "12:34::78");

erhalten wir die Liste:

("12", "34", "", "78")

Die Regex ˹:˼ passt dreimal, also werden vier Elemente zurückgegeben. Der Leerstring als drittes Element besagt nur, dass die Regex zweimal hintereinander gepasst hat, ohne dass es irgendwelchen Text dazwischen gab.

Leere Elemente am Ende

Normalerweise werden leere Elemente am Ende nicht zurückgegeben. Bei

@nums = split(m/:/, "12:34::78:::");

erhalten wir genau die gleichen vier Elemente

("12", "34", "", "78")

wie vorhin, obwohl die Regex am Ende des Suchstrings noch dreimal gepasst hat. Normalerweise entfernt split leere Elemente am Ende der Liste, außer man setzt den Limit-Operanden auf einen bestimmten Wert ...

Ein zweiter Job für den Limit-Operanden

Wenn der Limit-Operand explizit angegeben und nicht Null ist, dann wird dieses Entfernen von leeren Elementen am Ende der Rückgabeliste verhindert. (Bei Null verhält sich split genauso wie ohne den dritten Operanden.) Wenn die Anzahl der zurückgegebenen Elemente nicht eingeschränkt werden soll, aber das Entfernen der leeren Elemente am Ende doch verhindert werden soll, dann kann man einfach eine sehr große oder besser eine negative Zahl angeben: Negativ wird hier als »sehr, sehr groß« interpretiert. Mit split(/:/, $Text, -1) werden alle Elemente zurückgegeben, auch leere Elemente am Ende der Liste.

Wenn man als anderes Extrem überhaupt keine leeren Elemente will, auch die zwischendrin nicht, dann kann man vor dem split ein grep {length} einfügen. Das grep lässt nur die Elemente durch, die eine Länge größer als Null haben, also die nicht-leeren Elemente:

my @NichtLeere = grep { length } split(/:/, $text);

Besonderes Verhalten der Regex am Stringanfang

Wenn gleich am Anfang des Strings ein Treffer gefunden wird, ergibt das normalerweise ein leeres Element:

@nums = split(m/:/, ":12:34::78");

Das Array @nums erhält hier die folgenden Werte:

("", "12", "34", "", "78")

Das leere Element am Anfang zeigt, dass die Regex ganz am Anfang des Strings gepasst hat. Wenn jedoch die Regex am Anfang oder am Ende des Strings passt, aber keinen Text konsumiert (also auf eine Position passt), dann werden diese leeren Elemente nicht zurückgegeben. Bei split(/\b/, "Ein kleiner Test") passt die Regex an den sechs markierten Positionen in ›▵Ein▵▵kleiner▵▵Test▵‹. Trotz der sechs Treffer werden nicht sieben Elemente zurückgegeben, sondern nur fünf, nämlich ("Ein", " ", "kleiner", " ", "Test"). Diesen Spezialfall hatten wir eigentlich schon oben bei @Zeilen = split(m/^/m, $zeilen).

  

  

<< zurück vor >>

 

 

 

Tipp der data2type-Redaktion:
Zum Thema Reguläre Ausdrücke bieten wir auch folgende Schulungen zur Vertiefung und professionellen Fortbildung an:
   

Copyright der deutschen Ausgabe © 2008 by O’Reilly Verlag GmbH & Co. KG
Für Ihren privaten Gebrauch dürfen Sie die Online-Version ausdrucken.
Ansonsten unterliegt dieses Kapitel aus dem Buch "Reguläre Ausdrücke" denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

O’Reilly Verlag GmbH & Co. KG, Balthasarstr. 81, 50670 Köln