preg_split
(Auszug aus "Reguläre Ausdrücke" von Jeffrey E. F. Friedl)
preg_split(pattern, suchstring [, limit, [ flags ]])
Parameter
Der Pattern-Parameter: eine Regex mit Begrenzungszeichen, mit optionalen Modifikatoren (siehe Der »Pattern«-Parameter).
suchstring
Der Text, der in Teile zerlegt werden soll.
limit
Obere Grenze für die Anzahl Teile, in die der Text aufgeteilt werden soll.
flags
Optionale Flags, die das Verhalten der Funktion beeinflussen (siehe unten Optionen für preg_split):
PREG_SPLIT_NO_EMPTY
PREG_SPLIT_DELIM_CAPTURE
PREG_SPLIT_OFFSET_CAPTURE
Diese Flags können mit einem binären »Oder« beliebig kombiniert werden, wie im Beispiel unter Die Reihenfolge PREG_SET_ORDER.
Rückgabewert
Ein Array von Strings.
Erläuterungen
preg_split teilt einen String in Stücke auf und gibt sie in einem Array zurück. Mit dem optionalen limit-Parameter kann man die maximale Anzahl dieser Stücke angeben; das letzte Textstück bekommt dann »den ganzen Rest«. Mit den verschiedenen Flags kann man steuern, welche Textstücke wie zurückgegeben werden sollen.
In einem gewissen Sinn ist preg_split das Gegenstück zu preg_match_all: preg_split gibt die Textstücke zwischen den Treffern zurück. Anders gesagt: die Teile des Suchtexts, die übrig bleiben, wenn man die Treffer der Regex entfernt. preg_split ist das Regex-Pendant zu der einfacheren eingebauten PHP-Funktion explode.
Ein einfaches Beispiel: Auf einer Finanz-Seite kann man durch Leerzeichen getrennte Ticker-Symbole eingeben. Diese kann man mit explode voneinander trennen:
$tickers = explode(' ', $input);
Aber das berücksichtigt nicht, dass jemand eventuell mehrere Leerzeichen zwischen den Symbolen eingibt. Man nimmt besser ˹\s+˼ als Trennzeichen bei preg_split:
$tickers = preg_split('/\s+/', $input);
Es ist aber oft so, dass Benutzer – auch dann, wenn klar »durch Leerzeichen getrennt« gefordert wird – die Werte durch Kommas (oder Komma und Leerzeichen) trennen, also so etwas wie ›YHOO, AAPL, GOOG‹ angeben. Wir können auch das zulassen:
$tickers = preg_split('/[\s,]+/', $input);
Mit unserem Beispieltext bekommen wir ein $tickers-Array mit den drei Elementen ›YHOO‹, ›AAPL‹ und ›GOOG‹.
Auf Web-2.0-Sites wie Flickr werden Fotos oft kategorisiert, d.h. mit durch Kommas getrennten »Tags« versehen. In diesem Fall könnte man ˹\s*,\s*˼ benutzen und Leerzeichen vor und nach dem Komma zulassen:
$tags = preg_split('/\s*,\s*/', $input);
Es ist ganz instruktiv, die zwei Methoden mit ˹\s*,\s*˼ und mit ˹[\s,]+˼ zu vergleichen. Im ersten Fall wird bei einem Komma getrennt (es wird eines verlangt), aber vor und nach dem Komma darf Whitespace vorkommen. Bei einem $input von ›123,,,456‹ passt die Regex dreimal (bei jedem Komma), und preg_split gibt vier Elemente zurück: ›123‹, zwei leere Elemente und ›456‹.
Bei ˹[\s,]+˼ dagegen wird $input bei jedem Komma, jedem Leerzeichen oder bei Sequenzen von beiden aufgetrennt. Mit unserem Beispiel ›123,,,456‹ bekommen wir nur die zwei Elemente ›123‹ und ›456‹.
Der limit-Parameter bei preg_split
Durch die Angabe eines limit-Arguments kann man verlangen, dass preg_split nicht mehr als die angegebene Anzahl Teilstrings erzeugen soll. Wenn diese Anzahl vor dem Ende des Suchstrings erreicht wird, wird der ganze Rest des Suchstrings im letzten Element zurückgegeben.
Nehmen wir beispielsweise an, wir würden die HTTP-Kopfzeilen eines Servers »von Hand« decodieren. Nach dem Standard sind die Kopfzeilen von den Daten durch die vier Zeichen ›\r\n\r\n‹ getrennt, aber in der Realität kommt es oft vor, dass ein Server als Trennzeichen nur ›\n\n‹ schickt.
Mit preg_split kann man beide Fälle problemlos erledigen. Wenn wir die gesamte HTTP-Antwort des Servers in $response vorliegen haben, bekommen wir mit
$parts = preg_split('/\r? \n \r? \n/x', $response, 2);
die Kopfzeilen in $parts[0] und den Inhalt in $parts[1]. (Wir verwenden den x-Modifikator, damit die Regex übersichtlicher wird, siehe unter Regex-Modi.)
Das dritte Argument, 2, bedeutet, dass der Suchstring in nicht mehr als zwei Teile aufgeteilt werden soll. Wenn ein Treffer gefunden wird, wird der Teil des Suchstrings davor (nämlich die Kopfzeilen) zum ersten Element des Rückgabewerts. Der Rest des Strings muss nicht weiter abgesucht werden, denn das Limit ist bereits erreicht, und dieser Rest (der die Daten enthält) wird zum zweiten Element des Rückgabewerts.
Ohne Angabe eines limit-Werts (oder mit einem Wert von -1) würde der String möglicherweise in viel mehr Teile aufgespalten, und sehr wahrscheinlich würden die Daten dabei zerstört.
Die Angabe eines Limits garantiert aber nicht, dass der Rückgabewert ein Array mit so vielen Werten sein wird; es besagt nur, dass nicht mehr Elemente zurückgegeben werden (im Abschnitt zu PREG_SPLIT_DELIM_CAPTURE werden wir aber eine Situation vorfinden, wo genau das der Fall ist).
Es gibt zwei Situationen, bei denen die Angabe eines Limits sinnvoll ist. Die erste haben wir bereits kennengelernt: wenn gewünscht wird, dass das letzte Element »den ganzen Rest« bekommt. Im vorherigen Beispiel wollten wir eigentlich nur den ersten Teil (die Kopfzeilen) isolieren und den Rest (die darauf folgenden Daten) unberührt lassen. Dafür war unser 2 geeignet.
Ein Limit kann aber auch dann nützlich sein, wenn bekannt ist, dass nicht alle Elemente, die ein preg_split liefert, gebraucht werden. Wenn man beispielsweise eine Datei mit Personendaten hat, bei denen die Felder (»Vorname«, »Name«, »Adresse«, »Alter« usw.) durch ˹\s*,\s*˼ getrennt sind, und man nur an Vor- und Nachname interessiert ist, kann man ein limit von 3 einsetzen, damit preg_split nach den ersten zwei Feldern aufhört:
$felder = preg_split('/\s* , \s*/x', $personendaten, 3);
Alle weiteren Felder landen im dritten und letzten Array-Element, das man danach mit array_pop löschen oder auch einfach ignorieren kann.
Wenn man eines der flags (siehe den nächsten Abschnitt), aber keinen limit-Parameter angeben will, muss als Platzhalter der Wert -1 angegeben werden, dieser steht für »kein Limit«. Ein Wert von 1 bedeutet nichts anderes als »nicht aufteilen« und ist nicht besonders nützlich. Das Verhalten mit negativen Werten kleiner als -1 oder mit 0 ist nicht definiert, also verwenden Sie das besser nicht.
Optionen für preg_split
preg_split kennt drei Optionen, die sein Verhalten steuern. Diese können allein oder durch den binären »Oder«-Operator verknüpft angegeben werden (wie im Beispiel unter Das PREG_OFFSET_CAPTURE-Flag bei preg_match_all).
PREG_SPLIT_OFFSET_CAPTURE
Dieses Flag bewirkt dasselbe wie PREG_OFFSET_CAPTURE bei preg_match und preg_match_all, nämlich dass die Elemente des Rückgabewert-Arrays nicht die Teilstücke des Suchstrings sind, sondern selbst wieder Arrays, die die Offsets und die Teilstrings enthalten.
PREG_SPLIT_NO_EMPTY
Mit diesem Flag werden leere Elemente im Rückgabewert-Array unterdrückt; sie werden auch nicht gezählt, wenn die Anzahl der Elemente mit dem limit-Argument verglichen wird. Leere Elemente entstehen, wenn die Regex auf den Anfang oder auf das Ende des Suchstrings passt oder wenn Treffer direkt aufeinanderfolgen.
Im Beispiel mit den Flickr-Tags werden für den Text ›Party,,Fest‹ mit dem ursprünglichen Code
$tags = preg_split('/\s* , \s*/x', $input);
drei Elemente zurückgegeben: ›Party‹, ein leeres Element und ›Fest‹. Das leere Element entspricht dem »Nichts« zwischen den zwei Kommas.
Wenn das gleiche Beispiel mit der Option PREG_SPLIT_NO_EMPTY ausgeführt wird
$tags = preg_split('/\s* , \s*/x', $input, -1, PREG_SPLIT_NO_EMPTY);
erhalten wir nur die zwei Werte ›Party‹ und ›Fest‹.
PREG_SPLIT_DELIM_CAPTURE
Diese Option bewirkt, dass Text, der von einfangenden Klammern in der Trennzeichen-Regex eingefangen wurde, ebenfalls zum Resultat-Array hinzugefügt wird. Nehmen wir ein einfaches Beispiel: Ein String enthält Suchbegriffe, die durch ›und‹ oder ›oder‹ getrennt sind, beispielsweise:
DSLR Kamera und Nikon D200 oder Canon EOS 30D
Ohne das Flag PREG_SPLIT_DELIM_CAPTURE bekommen wir mit
$begriffe = preg_split('/\s+ (und|oder) \s+/x', $input);
ein $begriffe-Array mit den folgenden Werten:
array ('DSLR Kamera', 'Nikon D200', 'Canon EOS 30D')
Alle Teile des Strings, auf die die Trennzeichen-Regex gepasst hat, sind hier nicht mehr vorhanden. Mit PREG_SPLIT_DELIM_CAPTURE (und -1 als Platzhalter für den limit-Parameter)
$begriffe = preg_split('/\s+ (und|oder) \s+/x', $input, -1, PREG_SPLIT_DELIM_CAPTURE);
erhalten wir in $begriffe auch den Text, den die Klammern aufgefangen haben:
array ('DSLR Kamera', 'und', 'Nikon D200', 'oder', 'Canon EOS 30D')
In diesem Fall wird dem Resultat-Array für jede Trennstelle ein zusätzliches Element hinzugefügt, weil die Trennzeichen-Regex genau ein Klammerpaar enthält. In der weiteren Verarbeitung würden die Elemente ›und‹ und ›oder‹ gesondert behandelt.
Beachten Sie, dass PREG_SPLIT_DELIM_CAPTURE keine Wirkung hat, wenn nur-gruppierende Klammern (also hier '/\s+(?:und|oder)\s+/') verwendet werden; die Option bezieht sich nur auf einfangende Klammern.
Oder nehmen wir noch einmal unser Beispiel mit den Börsenticker-Symbolen:
$tickers = preg_split('/[\s,]+/', $input);
Wenn wir einfangende Klammern und die Option PREG_SPLIT_DELIM_CAPTURE hinzufügen
$tickers = preg_split('/([\s,]+)/', $input, -1, PREG_SPLIT_DELIM_CAPTURE);
geht vom ursprünglichen String gar nichts verloren, er wird einfach in Stücke zerlegt und im Array $tickers abgespeichert. Wenn dieses Array weiterverarbeitet wird, entsprechen die Elemente mit ungeraden Indizes der Klammer aus der Trennzeichen-Regex, ˹([\s,]+)˼. Das kann beispielsweise dann sinnvoll sein, wenn eine Fehlermeldung und der ursprüngliche Kontext ausgegeben werden sollen.
Übrigens – die Elemente, die als Folge der PREG_SPLIT_DELIM_CAPTURE-Option zurückgegeben werden, zählen nicht, wenn mit einem explizit angegebenen limit-Parameter verglichen wird. In diesem Fall kann das Resultat-Array mehr Elemente als das Limit enthalten (wenn die Trennzeichen-Regex mehrere Klammern enthält, können das auch sehr viel mehr sein).
Für Klammern am Ende der Regex, die nicht am Gesamttreffer teilhaben, werden keine Elemente im Resultat-Array erzeugt. Bei einem Klammerpaar, das nicht Teil des Treffers ist (siehe Leere Treffer-Elemente am Ende werden gekappt), kann es also sein, dass ein leerer String im Rückgabe-Array erzeugt wird, oder auch nicht. Ein leeres Element wird generiert, wenn es ein höher nummeriertes Klammerpaar gibt, das tatsächlich Anteil am Gesamttreffer hat; im anderen Fall wird kein Element im Rückgabe-Array erzeugt. Wenn außerdem die Option PREG_SPLIT_NO_EMPTY verwendet wird, gilt das alles nicht, weil in diesem Fall überhaupt keine leeren Elemente zurückgegeben werden.
<< 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