Erneute Suche nach einem Regex
lima-city → Forum → Programmiersprachen → PHP, MySQL & .htaccess
all
beschreibung
code
dank
ergebnis
falle
folgenden string
grundproblem
http
match
pos
problem
rand
string
teil
test
trennen
url
vorhaben
vorstellung
-
Guten Morgen,
wie versprochen, suche ich noch einen Regex für preg_match. Diesmal denke ich jedoch, dass mein Vorhaben nicht all zu kompliziert sein sollte für jene, die sich mit dem Quark auseinandersetzen.
Es geht um folgenden String:
Text1;Text2=Text3
Der Regex sollte nun folgendes Matchen:
Text1
Text2
Text3
Hierbei ist anzumerken, dass =Text3 nicht zwangsmäßig vorhanden ist. Der String könnte also auch so aussehen:
Text1;Text2
Das war's eigentlich =)
Bisher hatte ich mittels preg_split bzw. explode einfach den String zerschnitten, aber das Ergebnis gefällt mir so absolut nicht. Bemerken sollte ich ggf. noch, dass Text3 lediglich eine URL ist/sein sollte. Wenn Text3 nicht angegeben ist, KANN auch Text2 eine URL sein. Das Ganze filtere ich aber seperat raus. Dazu fehlen mir jedoch momentan halt die Matches =) -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage
-
ersetze doch die = durch ; und explode dann auf ;?
ist vielleicht sogar fixer, als es über preg_match zu lösen.
Ach btw, du bist nicht der einzige, der Regex als neuen Freund gefunden hat :D
Beitrag zuletzt geändert: 21.2.2011 11:03:49 von sneppa -
Ungetestet, sollte aber hinhauen.^(.+);(.+)=(.+)$
So aus Interesse: was spricht dagegen, einfach 2 explode()'s zu verwenden? Das wäre bei so einer einfachen Aufgabe unter Umständen sogar schneller. -
Das mit den Explodes klappt nicht ohne Weiteres, weil Text3 wie erwähnt, eine URL sein kann und dann auch dort = exploded wird, wobei ich hier mit Limit arbeiten könnte, was aber auch möglicherweise zu einem falschen Ergebnis führen kann. Aber danke soweit, ich probiers mal aus :)
EDIT:
Jetzt weiß ich auch wieder, was das Problem ist/war: Text2 kann auch eine URL sein. Wenn ich den o.g. Regex anwende und Text3 nicht vorhanden ist (aber selbst wenn es vorhanden wäre), wird bei einem möglicherweise in Text2 vorhandenen = gematcht, was wiederrum nicht passieren darf.
Bin grad erst aufgestanden, dauert etwas, bis das Hirn funktioniert =)
Hier zwei simple Beispiele:
Test;Lima-City=http://www.lima-city.de/?rand=12345
bzw:
Lima-City=http://www.lima-city.de/?rand=12345
Gematcht werden sollen:
Test Lima-City http://www.lima-city.de/?rand=12345
bzw:
Lima-City http://www.lima-city.de/?rand=12345
Beitrag zuletzt geändert: 21.2.2011 16:52:36 von fabo -
Das lässt sich trotzdem mit explode() sehr einfach machen:
<?php $arr = explode(';', $string); $firstPart = $arr['0']; $secondPart = $arr['1']; // wenn du willst, kannst du noch prüfen, ob das überhaupt existiert if (($firstPart != '') && ($secondPart != '')) { $firstPartArr = explode('=', $firstPart, 2); $firstPartOut = $firstPartArr[0]; if (isset($firstPartArr[1])) { $firstPartOutUrl = $firstPartArr[1]; } $secondPartArr = explode('=', $secondPart, 2); $secondPartOut = $secondPartArr[0]; if (isset($secondPartArr[1])) { $secondPartOutUrl = $secondPartArr[1]; } } else { // kein match } ?>
-
Wo wir dann zu dem Ergebnis kämen, dass
Test;Lima-City=http://www.lima-city.de/?rand=12345
zwar richtig matcht, jedoch
Test;http://www.lima-city.de/?rand=12345
nicht, weil $secondPartArr auf 2 limitiert ist, wogegen es nur auf max. 1, eher 0 limitiert sein dürfte.
Ich friemel das gleich mal aus, denn einen ähnlichen Ansatz hatte ich ja bereits. Die Ergebnisse waren aber immer gleich bescheiden....
EDIT:
Sollte eigentlich so reichen:
$arr = explode(';', $string); $exp[] = $arr[0]; $firstPartArr = explode('=', $arr[1], 2); $exp[] = $firstPartArr[0]; if (isset($firstPartArr[1])) { $exp[] = $firstPartArr[1]; }
Liefert aber auch noch das Selbe Ergebnis wie zuvor. Logischerweise ;)
Beitrag zuletzt geändert: 21.2.2011 17:48:13 von fabo -
fabo schrieb:
Achso, ich dachte, dass die Beschreibung immer vorhanden sein würde und nur die URL weg fallen würde. Dann müsste man prüfen, ob die Beschreibung eine URL (geht auch wieder ohne Regex) ist, wenn nicht, ist sie wirklich eine Beschreibung, wenn doch, ist sie eine URL. Das hast du aber übrigens nicht so beschrieben.
Wo wir dann zu dem Ergebnis kämen, dass
zwar richtig matcht, jedochTest;Lima-City=http://www.lima-city.de/?rand=12345
nichtTest;http://www.lima-city.de/?rand=12345
-
Bemerken sollte ich ggf. noch, dass Text3 lediglich eine URL ist/sein sollte. Wenn Text3 nicht angegeben ist, KANN auch Text2 eine URL sein.
Doch, hab ich -
fabo schrieb:
Hmm, das habe ich wohl nicht so ganz mitbekommen, den ersten Satz in deinem Zitat habe ich aber auf alle Fälle gelesen, sonst hätte ich den Code nicht so geschrieben.
Doch, hab ich
Auch wenn eine URL ohne Bezeichnung aus meiner Sicht keinen Sinn macht: Schreibe den Code einfach so um, wie ich es dir beschrieben habe, dann dürfte das passen. -
Wenn deine "Test2" keine = enthält, dann ginge das:
Ansonsten wäre das wieder eine Frage für nikic, der hat doch beim letzten mal auch so einen Irren Ausdruck zusammengeschustert.(?:([^;]+);)?([^=]+)=(.+)
Mit freundlichen Grüßen -
Das "wenn" ist das Problem =)
-
Ich hätte noch diesen hier, setzt allerdings vorraus, das die url immer mit "http" beginnt ;)
([^;]+);((http.+)|(.+)=(http.+))
Wenn nicht, das http einfach mit (http|ftp|bla...) ersetzen ^^ -
Ok, jetzt ist das Problem ein anderes ;)
Das geht dennoch ohne komplizierte reguläre Ausdrücke, die man später evtl verändern möchte und nicht kann.
Ich würde so vorgehen:
Nach ; exploden
Nach erstem Vorkommen des = mit strpos() suchen.
Und dann nach diesem Trennen!
Ungeprüft:
$string = "Test;Lima-City=http://www.lima-city.de/?rand=12345"; $teile = explode(";", $string); foreach ($teile AS $teil) { $pos = strpos($teil, "="); if ($pos > 0) { echo substr($teil, 0, $pos).'<br>'; echo substr($teil, $pos+1).'<br>'; } else { echo $teil.'<br>'; } }
Ausgabe natürlich nur Beispiel.
Mit dem Code hättest du auch später noch die Chance weitere Ausnahmen hinzuzufügen.
Beitrag zuletzt geändert: 22.2.2011 9:38:07 von sneppa -
Wo wir wieder beim Grundproblem wären, dass wenn Text3 nicht existiert, Text2 eine URL mit beinhaltendem Gleichzeichen ein falsches Ergebnis liefert:
Test http://www.lima-city.de/?rand 12345
-
Da hast du recht ;)
$string = "Test;Lima-City=http://www.lima-city.de/?rand=12345"; $teile = explode(";", $string); foreach ($teile AS $teil) { $pos = strpos($teil, "="); $pos2 = strpos($teil, "?"); if ($pos > 0 && $pos2 > 0 && $pos2 > $pos) { echo substr($teil, 0, $pos).'<br>'; echo substr($teil, $pos+1).'<br>'; } else { echo $teil.'<br>'; } }
-
Nicht schön, aber selten =) Danke, scheint so weit zu funktionieren.
-
Habs eben getestet, leider war es nicht ganz richtig.
$string = "Test;d=http://www.lima-city.de/??=rand12345"; $teile = explode(";", $string); foreach ($teile AS $teil) { $pos = strpos($teil, "="); $pos2 = strpos($teil, "?"); if ($pos > 0 && ($pos2 == 0 || ($pos2 > 0 && $pos2 > $pos))) { echo substr($teil, 0, $pos).'<br>'; echo substr($teil, $pos+1).'<br>'; } else { echo $teil.'<br>'; } }
Beitrag zuletzt geändert: 22.2.2011 11:20:29 von sneppa -
Hab ich nicht einmal gemerkt, aber danke :)
-
So, ich kann leider immer erst später am Abend antworten, aber ich habe mir dein Problem nochmal genauer angesehen und dann folgenden RegEx daraus gebaut:
(hier kannst du den grafisch aufbereitet sehen)(?:([^;]+);)?([^=\?]+\?(?:[^=&]+(?:&|=(?:[^&]+&|[^=]+)))*|[^=]+)(?:=(.+))?
Der Regex filtert, im Gegensatz zu @drafed-map`s Lösung, alle eindeutigen Möglichkeiten korrekt.
Nicht eindeutig sind z.B.:
und ähnliche andere.Test;d?a=http://www.lima-city.de/a=b Test;d?a=http://www.lima-city.de/?a=b Test;d?a=lima-city.de/a=b
Als Referenzimplentierung habe ich diesen Code auf der Konsole ausgeführt:$tests = array( "Test;d=http://www.lima-city.de/", "Test;d=http://www.lima-city.de/?test=a", "Test;d=http://www.lima-city.de?test=a", "Test;d=http://www.lima-city.de/?test", "Test;d?=http://www.lima-city.de/", "Test;d?a=b=http://www.lima-city.de/", "Test;d?a=b&c=d=http://www.lima-city.de/", "Test;d?a&=http://www.lima-city.de/", "Test;d?a=b&=http://www.lima-city.de/", "Test;d?a=http://www.lima-city.de/", "Test;d?a=http://www.lima-city.de/?a=b", "Test;d?a=http://www.lima-city.de/=", "Test;d?a=http://www.lima-city.de/", "Test;d?a", "Test;d?a= =http://www.lima-city.de/", // ...a==http... ergab komische ergebnisse ); foreach($tests as $test) { preg_match("_(?:([^;]+);)?([^=\?]+\?(?:[^=&]+(?:&|=(?:[^&]+&|[^=]+)))*|[^=]+)(?:=(.+))?_", $test, $m); print_r($m); }
Beitrag zuletzt geändert: 22.2.2011 23:01:33 von nemoinho -
Hi,
das sieht schick aus. Auf den ersten Blick entspricht das Ergebnis auch meinen Vorstellungen. Ich werds testen. Danke dafür :) -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage