PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : ereg_replace funktioniert nicht


fab
06.09.2007, 19:02:01
Hallo zusammen,

dies ist meine erste Frage in diesem Forum. Zuerst mal zum Hintergrund: Der User soll Texte auf seiner Internetseite selber updaten können. Die Eingabe erfolgt über textareas, die Speicherung übernimmt eine MySQL-Datenbank. Das klappt alles kanz gut. Bei der Texteingabe sollen dem User keine HTML tags gestattet sein, bzw. ich eliminiere diese später mit strip_tags($text). Es sollen aber dennoch einige einfache Formatierungen möglich sein (fett, kursiv, Zeilenwechsel, emailadresse und webadresse). Auch das ist noch kein Problem: Mit einer kleinen Javascript-Funktion kann der User die Formatierung direkt im Textfeld bei der Eingabe vornehmen; das ganze sieht dann so aus:

google dochmal (http://www.google.de)

Im Prinzip funktioniert das ganz ähnlich wie bei der Texteingabe hier in diesem Forum. Jetzt kommt mein Problem: Bei der Ausgabe der Seite, soll das natürlich in normales HTML konvertiert werden. Ich habe hierzu (in mühsamer Kleinarbeit) die folgende Anweisung zusammengebastelt:

$text = ereg_replace("(\[URL\=)(.*)(\])(.*)(\[/URL\])", "<a href=\\2 target=_blank>\\4</a>", $text);

Das funktioniert aber nur dann, wenn in dem eingegebenen Text nur eine einzige zu ersetzende URL vorkommt. Bei mehreren URLs gibts "Kraut und Rüben". Ich stelle hier schon seit Stunden alles um und bekomme das nicht hin. Habe auch schon alles mögliche zu RegEx u.ä. gelesen, aber irgendwie sehe ich nur noch slashes und Sternchen...

vielleicht kann jemand helfen?
fab

rambi
06.09.2007, 21:17:48
http://www.christian-seiler.de/projekte/php/bbcode/

z0iD
06.09.2007, 21:21:21
Das liegt daran, dass die Regex Auswertung gierig ist. Wenn Du mal .* durch [^[]* ersetzt müsste es gehen. Dann darf zwischen dem [URL] Einschluß keine eckige öffnende Klammer auftauchen.

fab
06.09.2007, 22:42:41
Vielen Dank!

das hilft mir schon mal echt weiter. Irgendwie muss man bei diesen Regulären Ausdrücken auf eine Art denken, mit der ich Probleme habe...

fab

z0iD
07.09.2007, 07:19:27
Das Problem dabei ist natürlich dass Du dann soetwas nicht machen kannst:
(url=http://domain.de)text (b)fetter text(/b) noch ein text(/url) Wenn Du soetwas zulassen möchtest, wirds noch ein bisschen schwerer und der Ausdruck länger. Du musst dann ausschließen dann die Zeichenkette [/url] innherhalb auftaucht. Das bedeutet im Konkreten:
Es darf (/url auftreten, solange danach ein Zeichen kommt, welches von ) verschieden ist.
Es darf (/ur*) auftreten, solange * eine von l verschiedene Zeichenkette ist.
usw.

Du stößt da auf das größte Problem, was man mit REGEX bekommen kann, undzwar, wenn man versucht, eine ganze Zeichenkette auszuschließen.


___
Anm.: Ich habe die eckigen Klammern mal durch runde ersetzt.

fab
07.09.2007, 08:22:48
Hallo z0iD,

Danke nochmal für die weitere Info! Den Code von gestern habe ich eingebunden und auch verstanden (denke ich). Die Problematik, die du ansprichst, ist mir klar und ich werde versuchen, das dementsprechend weiterzuentwickeln. Vielleicht finde ich ja noch eine gute Dokumentation zu dem Thema. Jetzt bin ich erst mal froh, dass das so geht, wie ich es mir vorgestellt hatte...

fab

z0iD
07.09.2007, 10:31:01
Da ich schon lange nach einer Lösung dafür suche, habe ich nochmal drüber nachgedacht. Ich denke der Text zwischen den Klammern müsste durch folgenden Ausdruck korrekt erkannt werden;

(a) (b) (c) (d) (---e---)
( ([^[]*) ((\[ ( [^/] | /[^u] | /u[^r] | /ur[^l] | /url[^\]] ) )?) )*
Da es schwer wahrnehmbar ist, der Versuch einer Erläuterung:
Zunächst dürfen beliebig viele Zeichen kommen, die keine öffnende eckige Klammer sind (a).
Wird jedoch ein Zeichen gelesen, welches eine solche Klammer ist (b), so müssen bestimmte Bedingungen erfüllt sein, undzwar, darf das darauf folgende Zeichen kein Schrägstrich sein (c). Wenn es ein Schrägstrich ist, darf ohne weiteres kein u folgen (d). So geht das dann weiter, bis man schließlich nur noch das höchste der Gefühle, nähmlich (e) zulässt.

Wenn man das dann für alle Begrenzer macht, ist man ne ganze Weile beschäftigt. Der arme Prozessor der das interpretieren darf übrigens auch :)

Einfacher hätte man es wohl, wenn man vorher (via str_replace) die ganzen Begrenzer durch atomare Sonderzeichen ersetzt. Nur dürfen jene dann nicht in dem eigentlichen Text vorkommen.

rambi
07.09.2007, 11:51:48
<querschläger>
1. ereg_* ist viel lahmer als preg_*
2. egal wie, aber mit regulären Ausdrücken kann man kein "korrektes" HTML nach der auflösung der BBCodes garantieren!
3. also muß eigendlich ein echter Parser eingesetzt werden
</querschläger>

fab
07.09.2007, 13:25:44
@z0iD: Ja, Wahnsinn!

z0iD
07.09.2007, 15:04:00
<querschläger>
1. ereg_* ist viel lahmer als preg_*
2. egal wie, aber mit regulären Ausdrücken kann man kein "korrektes" HTML nach der auflösung der BBCodes garantieren!
3. also muß eigendlich ein echter Parser eingesetzt werden
</querschläger>

Was ist XML (ich lass mal die HTML-Suppe außen vor) für eine Sprache? Ist die nicht regulär?

*denk* ... ne, richtig, kann nicht regulär sein, da sie ja wohlgeformt sein muss (für jedes öffnende Tag ein schließendes und auchnoch das korrekte, folglich braucht man einen unendlichen Speicher (Kellerspeicher)). Dann ist sie wohl nur kontextfrei, also Typ 2. Folglich kann sie also nicht von einer regulären Grammatik bzw. einem regulären Ausdruck beschrieben werden.
Allerdings klaffen manchmal Theorie und Praxis auseinander. Wenn Du nur eine endliche Verschachtelung zulässt, ist sie darstellbar (wenn auch vermutlich sehr kompliziert).

Allerdings, meinst Du mit Deinem "echten Parser" wahrscheinlich einen deterministischen endlichen Automaten. Der wiederum die selbe Ausdrucksstärke besitzt wie ein regulärer Ausdruck. Für eine Typ 2 Sprache bräuchtest Du schon nen Kellerautomaten.


Aber das mit dem ereg_ versus preg_ muss mir nochmal wer erklären. Was ist denn da der Unterschied?

rambi
07.09.2007, 15:30:49
Die von mir vorgeschlagene Klasse erzeugt eine Baumstruktur. So kann dann wirkungsvoll zb. das Vorkommen von <ul> in <b>bla bla</b> verhindert werden.
Dieses ist nämlich verboten.

preg <->ereg: Ich habe das irgendwo gelesen.
Und dann aber auch getestet. Bei etwas komplexen Ausdrücken ist mit einer Performancesteigerung von ca. Faktor 5 zu rechnen(sagen meine Tests)

Zusätzlich: Meines Wissens nach, werden die ereg* Funktionen aus PHP6 rausfliegen

z0iD
07.09.2007, 16:15:00
Die Klasse sieht - ohne sie getestet zu haben - recht vernünftig aus.
(Vor allem die Gestaltung der zugehörigen Seite hats mir angetan)

Die preg vs. ereg Geschichte ist mir suspekt. Da muss es doch einen Nachteil geben.
Ich weiß nicht, wie Du Deine Tests durchgeführt hast, aber vielleicht sind beide Funktionen auf unterschiedliche Fälle optimiert, und Du hast grade den preg Fall erwischt.

PHP6: Dann muss ich mich wohl schonmal mit preg anfreunden, ich benutze immer eregi.

meikel (†)
07.09.2007, 17:43:21
Zusätzlich: Meines Wissens nach, werden die ereg* Funktionen aus PHP6 rausfliegen
http://new-bbs.de/info/funktionen.php
[1349] => ereg
[1350] => ereg_replace
[1351] => eregi
[1352] => eregi_replace

defabricator
07.09.2007, 19:40:13
http://php6dev.blogspot.com/#move-ereg-to-pecl
Conclusions:

1. We make ereg an extension

2. The PCRE extension will not be allowed to be disabled.

3. The core of PHP should be made to work with PCRE so that we can safely
disable ereg

4. We unbundle the regex librarysteht noch auf der TODO Liste, wird aber sicher kommen.