XHTMLforum

XHTMLforum (http://xhtmlforum.de/index.php)
-   Serveradministration und serverseitige Scripte (http://xhtmlforum.de/forumdisplay.php?f=80)
-   -   RegEx (PCRE): Schließende Tags ergänzen? (http://xhtmlforum.de/showthread.php?t=39863)

Ulti 09.05.2006 00:39

RegEx (PCRE): Schließende Tags ergänzen?
 
Hallo!

Ich verzweifle im Moment gerade an einem RegEx, der, falls in einem String ein HTML-Tag geöffnet, aber nicht geschlossen ist, den schließenden ergänzt. Beispiel:

Code:

Hallo


Nun möchte ich ein
ergänzen.

Ich habe zwei Ansätze versucht:

1. Ich habe mit einer Fallunterscheidung prüfen wollen, ob der öffnende Tag existent ist, der zweite aber nicht:

Code:

<?php

if (preg_match('%<(em|strong)>%Ui', $string) && !preg_match('%</\1>%Ui', $string)) {
    $string .= '</\1>';
}

?>

Das Problem daran: Mit \1 kann ich nicht auf Subpatterns aus dem ersten RegEx zugreifen -> es spuckt einen Fehler aus, der sagt, dass \1 im zweiten RegEx nicht existiert. Kann ich irgendwie auf Subpatterns aus anderen RegExen zugreifen?

2. Ich wollte mit folgendem Code nach Strings suchen, die öffnende, aber keine schließenden Tags beinhalten, und dann durch den selben String mit einem schließenden Tag am Schluss ersetzen:
Code:

<?php

    preg_replace('%<(em|strong)>(.*)(^</\1>)%Uis', '<\1>\2</\1>', $string);

?>

diser Code will aber nicht funktionieren. Was mache ich da falsch?

Wäre für jede Hilfe dankbar, ob's jetzt ne Reaparatur von obigem Code ist, oder nochmal ein anderer Ansatz

derHund 09.05.2006 10:48

Zitat:

Kann ich irgendwie auf Subpatterns aus anderen RegExen zugreifen?
nicht in form einer stinknormalen backref - woher sollte die pcre-engine auch wissen, ob du jetzt backref1 aus aktuellem oder vorherigem oder sonstigem pattern meinst? du kannst dir die subpattern einer auswertung als array zurückgeben lassen, die dann weiterverwenden (simple stringverkettung).
Zitat:

Was mache ich da falsch?
nen zirkumflex am nicht-anfang und außerhalb von zeichenklassen ist sinnlos. wenn du einzelne zeichen negieren willst, mußt du [^] verwenden - da du aber eine folge von mehreren zeichen negieren willst, ... is nicht - nicht auf diesem wege. sieh dir mal assertions an - die komplexeren, nicht die einfachen wie ^ oder $ - die lookahead/behind meine ich (manual ganz unten).

damit ich dir helfen kann, muß ich genau wissen, wie die bedingungen sind, die vorliegen. pcre ist ne formale sprache, das heißt, wenn du exakt (in normaler sprache) formulieren kannst, was du machen willst, kann man es meisten sehr einfach übersetzen.

ansonsten: entweder per assertion oder per rekursiven pattern (ja nach bedingungen).

zum testen: http://pcre.nophia.de/evaluate/index.php (ich würd dir ja selbst was aufstellen, hab aber keine zeit - hab durch den ewigen text hier schon ewig zeit verschwendet :roll: ;) - eventuell heut abend ... )

was machst du, wenn nur der schließende tag existiert? eigentlich ein interessantes thema, werd mal irgendwann etwas dazu schreiben.

achso - je nach situation hilft dir dieser beitrag vielleicht: http://www.php-resource.de/forum/sho...threadid=45908 - vielleicht ists auch overpowered, ka.

psycho_dmr 09.05.2006 10:54

erstma ne blöde frage, wie willst du wissen, wo der tag wider geschlossen werden soll?

und zu 1.
ich glaub du das da nur n syntaxfehler drin.. dein $treffer fehlt..
http://www.php.net/manual/de/function.preg-match.php

Code:

<?php

if (preg_match('%<(em|strong)>%Ui', $string, $treffer) && !preg_match('%</'.$treffer[1].'>%Ui', $string)) {
    $string .= '</'.$treffer[1].'>';
}

?>

code ist ungeprüft, aber so in etwa müsste das glaub ich aussehen.

zu 2. kann ich nix sagen, ich kapier weder dein text noch den code da, sry ^^

__edit: derhund war schneller -.- ^^

Ulti 09.05.2006 15:44

@psycho_dmr

deine Lösung klappt, jedoch schließt er dann nur einen Tag. Sind mehr als einer ungeschlossen, bleiben die restlichen halt offen. Da muss man wohl irgendwie mit einer Schleife mehrmals drüber. Muss ich nacher mal schauen.

Zitat:

erstma ne blöde frage, wie willst du wissen, wo der tag wider geschlossen werden soll?
Es würde reichen, wenn einfach am schluss vom string das schließende Tag steht, damit, wenn ich diesen String ausgeben lasse, nicht alles was nach diesem String folgt, auch noch davon betroffen ist.

@derHund

Zitat:

nicht in form einer stinknormalen backref - woher sollte die pcre-engine auch wissen, ob du jetzt backref1 aus aktuellem oder vorherigem oder sonstigem pattern meinst? du kannst dir die subpattern einer auswertung als array zurückgeben lassen, die dann weiterverwenden (simple stringverkettung).
Das wäre ja dann genau das, was psycho_dmr vorgeschlagen hat, oder?

Zitat:

was machst du, wenn nur der schließende tag existiert?
Daran habe ich allerdings noch überhaupt nicht gedacht. Das könnte man ja dann so ähnlich prüfen, wie oben, nur halt andersherum, oder?

Zitat:

damit ich dir helfen kann, muß ich genau wissen, wie die bedingungen sind, die vorliegen.
Ich möchte, falls einer der tags [i],[b],<del> oder <ins> in einem Tag geöffnet, aber nicht geschlossen ist, diesen schließenden Tag am Schluss des Strings hinzufügen. Es ist eigentlich ein ganz normaler string, keine addslashes() oder so.


Der link zu php-resource.de funktioniert leider nicht, da muss ich wohl registriert sein

Der punkt ist halt, dass ich mich noch nicht lang mit RegExen beschäftige, bin noch in der lernphase ;)

Ulti 09.05.2006 20:01

Sorry für den Doppelpost, aber ich hab das Problem gelöst! :D

Code:

<?php

        preg_match_all('%<(strong|em)>%Ui', $string, $treffer);
        $treffer[1] = array_reverse($treffer[1]);
        foreach ($treffer[1] AS $sub) {
                if (preg_match('%<'.$sub.'>%Ui', $string, $subpattern) && !preg_match('%</'.$sub.'>%Ui', $string)) {
                        $string .= '</'.$sub.'>';
                }
        }

?>


Habe aber noch über einen anderen ansatz nachgedacht, darstellungsfehler bei nicht geschlossenen Tags zu vermeiden:

Man bearbeitet vorher den String mit htmlspecialchars(), und ersetzt dann alle &lt; und &gt; die zu vollständigen Tag-Pärchen gehören, durch < und >. Muss ich aber noch probieren.

Vielen dank euch beiden für bei eure hilfe! 8)


Alle Zeitangaben in WEZ +2. Es ist jetzt 02:38 Uhr.

Powered by vBulletin® Version 3.8.11 (Deutsch)
Copyright ©2000 - 2024, vBulletin Solutions, Inc.

© Dirk H. 2003 - 2023