Ersetzen ohne HTML zu zerstören
September 2009
Etwas zu ersetzen oder hervorzuheben ohne den HTML-Code zu zerstören ist nicht ganz so einfach. Mit ein bisschen Regex funktioniert es dennoch.
Im folgenden Beispiel wird die Zeichenfolge "spa" hervorgehoben (fett geschrieben), ohne den <span>-Tag zu beeinflussen.
Im nächsten Beispiel wird ein Zeichen ersetzt.
Nach diesem Prinzip lassen sich auch andere Sachen machen, beispielsweise einen Text in Leetspeak übersetzen:
Siehe auch:
Im folgenden Beispiel wird die Zeichenfolge "spa" hervorgehoben (fett geschrieben), ohne den <span>-Tag zu beeinflussen.
<?php
$text = 'Ich suche spanisches <span style="color:#ff0;">Geld</span>!';
$gesucht = 'spa'; // der gesuchte String
$links = '<b>'; // linker Begrenzer
$rechts = '</b>'; // rechter Begrenzer
$links_Q = preg_quote($links, '#');
$rechts_Q = preg_quote($rechts, '#');
$gesucht_Q = preg_quote($gesucht, '#');
while(preg_match('#(>|^)[^<]*(?<!'.$links_Q.')'.$gesucht_Q.'(?!'.$rechts_Q.')[^>]*(<|$)#isU', $text)) // damit auch wirklich alles ersetzt ist
$text = preg_replace('#(^[^<]*|>[^<]*)(?<!'.$links_Q.')('.$gesucht_Q.')(?!'.$rechts_Q.')([^>]*<|[^>]*$)#isU', '${1}'.$links.'${2}'.$rechts.'${3}', $text);
echo $text;
# Ich suche <b>spa</b>nisches <span style="color:#ff0;">Geld</span>!
?>
Mit diesen Regex wird überprüft, ob sich der gesuchte String nicht zwischen < und > befindet, bzw. ob er ausserhalb eines HTML-Tags steht. Ebenfalls wird mit Look-Around-Assertions kontrolliert, dass das Suchwort nicht bereits verarbeitet worden ist, da das Skript sonst in einer Endlosschleife enden würde, weil derselbe String mehrmals (unendlich Mal) verarbeitet werden würde.Im nächsten Beispiel wird ein Zeichen ersetzt.
<?php
$text = 'Ich suche spanisches <span style="color:#00f;">Geld</span>!';
$gesucht = 's'; // das gesuchte Zeichen oder Zeichenfolge
$ersetzt = '$'; // das ersetzte Zeichen oder Zeichenfolge
while(preg_match('#(>|^)[^<]*'.preg_quote($gesucht,'#').'[^>]*(<|$)#isU', $text))
$text = preg_replace('#(>[^<]*|^[^<]*)'.preg_quote($gesucht,'#').'([^>]*<|[^>]*$)#isU', '${1}'.$ersetzt.'${2}', $text);
echo $text;
# Ich $uche $pani$che$ <span style="color:#ff0;">Geld</span>!
?>
Hier darf der String $gesucht nicht in $ersetzt vorkommen, weil daraus unmittelbar eine Endlosschleife zur Folge hätte.Nach diesem Prinzip lassen sich auch andere Sachen machen, beispielsweise einen Text in Leetspeak übersetzen:
<?php
$text = 'Ich kann das <strong>nicht</strong> lesen.';
$leets = array('a'=>'4','b'=>'8','c'=>'©','d'=>'Ð','e'=>'3','f'=>'ƒ','g'=>'6',
'h'=>'#','i'=>'!','j'=>'_|','k'=>'K','l'=>'1','m'=>'M',
'n'=>'N','o'=>'0','p'=>'|°','q'=>'0_','r'=>'|2','s'=>'5','t'=>'7',
'u'=>'µ','v'=>'\/','w'=>'W','x'=>'%','y'=>'¥','z'=>'2');
foreach($leets as $orig => $leet)
while(preg_match('#(>|^)[^<]*'.$orig.'[^>]*(<|$)#isU', $text))
$text = preg_replace('#(>[^<]*|^[^<]*)'.$orig.'([^>]*<|[^>]*$)#isU', '${1}'.$leet.'${2}', $text);
$text = str_replace(array('K','M','N','W'), array('K','M','N','W'), $text);
/* Vier Buchstaben sollten nur in Grossschreibung umgewandelt, jedoch nicht
ersetzt werden. Allerdings mussten die entsprechenden Enitites verwendet
werden, da sonst auch hier eine Endlosschleife entstehen würde. */
echo $text;
# !©# K4NN Ð45 <strong>N!©#7</strong> 1353N.
?>
Siehe auch:
