[PHP/RegExp] rekursiver Funktionsaufruf *vorerst erledigt*

strolch00

redraft.de
ID: 155297
L
21 April 2006
1.684
72
Hi @all,

ich spiele gerade mal bisschen mit RegExp und rekursion rum, dabei stoße ich auf ein Problem wo ich grad häng.

Folgender Code:
PHP:
<?php
function _bbcode($string)
{
	$match = array();
	$rep_array = array(1 => array('b', '<b>', '</b>')
							, 2 => array('ol', '<ol>', '</ol>')
							, 3 => array('ul', '<ul>', '</ul>')
							, 4 => array('i', '<i>', '</i>')
							, 5 => array('u', '<u>', '</u>')
							, 6 => array('sub', '<sub>', '</sub>')
							, 7 => array('sup', '<sup>', '</sup>')
							, 8 => array('h1', '<h1>', '</h1>')
							, 9 => array('h2', '<h2>', '</h2>')
							, 10 => array('pre', '<pre>', '</pre>')
							, 11 => array('quote', '<pre>', '</pre>')
							, 12 => array('url', '<a href="">', '</a>')
							, 13 => array('code', '<pre>', '</pre>')
							, 14 => array('img', '<img src="">', '</img>')
/*
							, '[]' => array('<>', '</>')
							, '[]' => array('<>', '</>')
							, '[]' => array('<>', '</>')
*/
							);


	foreach($rep_array AS $k => $v)
	{
		$pat = "@^([^\[".$v[0]."\]].*)?(\[".$v[0]."\])(.*)(\[/".$v[0]."\])(.*)?$@i";

		if(preg_match($pat, $string, $res))
		{
			$element = preg_replace("@\[/?".$v[0]."\]@i", '', $v[1].$res[3].$res[5].$v[2]);
			array_push($match, $element);

			if(preg_match($pat, $element))
				_bbcode($element);
			else
				continue;
		}
	}

	return array_pop($match);
}

 echo _bbcode("[B]DIES IST [B]EIN TEST[/B], FÜR REGEX[/B]! [H1]Mal sehen[/H1] [h2]obs funzt[/H2] *gespannt bin");
 echo "<br /><br />Quellcode:<br><pre>".htmlentities(_bbcode("[B]DIES IST [B]EIN TEST[/B], FÜR REGEX[/B]! [H1]Mal sehen[/H1] [h2]obs funzt[/H2] *gespannt bin"))."</pre>";
?>

Ich bin der Meinung es liegt am falschen Funktionsaufbau, aber wie soll ich das anders lösen? Ich steh irgendwie grad voll auf dem Schlauch und weis nicht weiter. Einen zweites element im Funktionsheader wäre machbar worin ich das aktuelle Arrayelement übergebe oder NULL. Aber das kann doch nicht die Lösung sein oder doch?

Danke

Die Ausgabe des Aktuellen Codes kann man hier sehen.
 
Zuletzt bearbeitet:
boah umständlicher gehts nicht?

wie wäre es den einfach mit
PHP:
preg_replace("~[b](.*?)[/b]~i","<b>\\1</b>",DIE EINGABE);
 
Ehm dann habe ich aber das Problem das er mir das erste [B\] und das erste [/B\] ersetzt. Oder sehe ich was falsch. Ich wusste nix einfacheres weil ich gleiche Verschachtelungen rausschmeisen will. Aber ich probier es mal.

*edit ganz unten das dritte wäre deine Variante.
 
Ehm dann habe ich aber das Problem das er mir das erste [B\] und das erste [/B\] ersetzt. Oder sehe ich was falsch. Ich wusste nix einfacheres weil ich gleiche Verschachtelungen rausschmeisen will. Aber ich probier es mal.

*edit ganz unten das dritte wäre deine Variante.

Das erste [.B] und das letzte [./B].
Für das, was du sagst, müsste als letzter Buchstabe noch ein U an den Ausdruck angehängt werden (ungreedy mode, ungieriger Modus) ;)

Und Verschachtelungen würde er entsprechend wirklich nicht raffen ;)

Ciao
 
Verdammt und ich habe es mit dem ? versucht weil es hies dadurch kann man greedy und ungreedy umschalten. Ohje manchmal kann das leben so einfach sein. Ich danke euch beiden. Dann brauch ich ja nur meinen Array zu überarbeiten und habe nur noch einen Funktion sehr schön. Danke
 
Verdammt und ich habe es mit dem ? versucht weil es hies dadurch kann man greedy und ungreedy umschalten. Ohje manchmal kann das leben so einfach sein. Ich danke euch beiden. Dann brauch ich ja nur meinen Array zu überarbeiten und habe nur noch einen Funktion sehr schön. Danke

du musst nur vorher einmal durch den quelltext gehen und die [.B] und [./B] durchnummerieren, dann weisst du auch gleich, ob was vergessen wurde...
 
mit preg_* allein kann man auch keine verschachtlubng berücksichtigen... spätestens wenn sowas wie

PHP:
asds[B]dsfdsf[/B] dsfsdf [B] dsffsdf[/B]dfg

kommt wars das.
 
mit preg_* allein kann man auch keine verschachtlubng berücksichtigen... spätestens wenn sowas wie

PHP:
asds[B]dsfdsf[/B] dsfsdf [B] dsffsdf[/B]dfg

kommt wars das.

warum nicht??

-> https://www.klamm.de/forum/showthread.php?p=1036089#post1036089

und fallst du das meintest:
PHP:
[b]acsihgfdhsd [b]sadadssad[/b] adsgdsafdsf[/b]
dann ist die zeile falsch, weil b zu verschachteln unsinn ist ... aber wie gesagt: meine "durchzählmethode" behebt solche probleme recht einfach...
 
dafür (bzw. dagegen) gibts den parameter /U für ungreedy. hatten wir doch hier schon geklärt...

ja ich weiß... aber das wollte strolch nicht. hab ja schon ne ganz einfach lösung gepostet gehabt.

PHP:
preg_replace("~[b](.*?)[/b]~i","<b>\\1</b>",DIE EINGABE);

aber die wollte stolch nicht weil dies nicht die tag paare berücksichtigt sondern immer nur das was als erste kommt nimmt.
zb aus
PHP:
[b]acsihgfdhsd [b]sadadssad[/b] adsgdsafdsf[/b]

würde
PHP:
<b>acsihgfdhsd [b]sadadssad</b> adsgdsafdsf[/b]
werden.
 
mit preg_* allein kann man auch keine verschachtlubng berücksichtigen... spätestens wenn sowas wie

PHP:
asds[B]dsfdsf[/B] dsfsdf [B] dsffsdf[/B]dfg

kommt wars das.

Jop das musste ich auch gerade eben feststellen, och menno is doch net so einfach. Aber durchzählen und dann ersätzen ist auch ziehmlich aufwendig finde ich, einfacher ginge es doch mit der preg_replace ohne U und dann innerhalb $1 schauen ob nochmal [B.] sind. Oder?
 
Aber durchzählen und dann ersätzen ist auch ziehmlich aufwendig finde ich, einfacher ginge es doch mit der preg_replace ohne U und dann innerhalb $1 schauen ob nochmal [B.] sind. Oder?

du kannst pauschal hingehen und z.b. jedes [ b] durch <b> und [ /b] durch </b> ersetzen, das ist richtig. dabei dürfte es auch schnuppe sein, ob du das mit str_replace oder preg_replace oder sonstwie machst.

wenn du sachen aber abchecken willst/musst und auf plausibilität prüfen, dann bleibt dir nicht viel übrig, als das ganze "abzuzählen" und rekursiv zu lösen. du gehst natürlich nicht den string durch und zählst alle vorkommen oder so einen blödsinn. mit abzählen meine ich, dass du ganz simpel gesagt für jeden open tag den du findest den NÄCHSTEN close-tag suchst. wenn vorher ein weiterer open-tag kommt, dann musst du ab sofort 2 weitere close-tags suchen etc.

du kannst auch nach deinem vorschlag vorgehen und den gefundenen string innerhalb der tags so lange wieder rekursiv in die funktion werfen, bis kein gültiger tag mehr gefunden wird und dann den ersetzten inhalt zurückgeben. ich fürchte aber, dass das ab einer gewissen text-grösse irsinnig viele iterationen werden und du unter umständen sekundenlang auf ein ergebnis warten musst :(
 
ich fürchte aber, dass das ab einer gewissen text-grösse irsinnig viele iterationen werden und du unter umständen sekundenlang auf ein ergebnis warten musst :(
Genau das habe ich mich auch gefragt, was ist nun besser alles mit regexp zu lösen und durchzugehen, oder deine Varianta abzuzählen. Aber wenn ich mir das so überlege scheint abzuzählen evtl. besser zu sein weil es grob geschätzt zwei if´s in der funktion und man belastet die regex engine nicht.

Hmm ok ich seh das ganze jetzt mal als erledigt an und bastel mal nen Benchmark bei Gelegenheit. weil ich jetzt weinen regex habe der alles so mach wie ich will. Also
"[.B]DIES IST [.B]EIN TEST[./B], FÜR REGEX[./B]! [.H1]Mal sehen[./H1] [.h2]obs funzt[./H2] *gespannt [.B]bin[./b]"
wird zu
DIES IST [.B]EIN TEST[./B], FÜR REGEX! [.H1]Mal sehen[./H1] [.h2]obs funzt[./H2] *gespannt bin
Und wenn ich dann alles einfach rausschmeiße was den style \[.*] hat ist das auch keine große belastung.

*wers wissen will der Regex ist teils von php.net abgeschaut.
Code:
// ohne _x_ in den []
#\[_x_indent]((?:[^[]|\[(?!/?indent])|(?R))+)\[/_x_indent]#
sowas in der Art. Aber über siesen regex muss ich mir selber erstmal klar werden was was macht:LOL:
 
vielleicht hilft dir das noch weiter: https://www.roonaan.nl/hotscripts/index.php?script=quickerubb.php ist zwar keine vollständige bbcode-implementation, aber das vorgehen ist auf geschwindigkeit optimiert ... habs selbst noch nicht genauer betrachtet, aber da ich auch gerade eine klasse dazu bauen muss/will ists mir bei der recherche mit aufgetaucht. alle anderen anwendungen, die ich gefunden habe waren immer sehr aufgebläht...