Suchmuster hervorheben mit preg_replace

Cusco

Erfahrenes Mitglied
Hi,

ich möchte ein Suchergebnis Hervorheben zum Beispiel durch Fettdruck oä. Als Ausgangsmaterial habe ich den Kompletten Ausgabepuffer welcher eine normale HTML-Seite darstellt und den Musterstring in einer Session-Variable. Nun möchte ich das jedes Wort des Musterstring im HTML-Code hervorgehoben wird unter Beachtung den HTML-Code nicht zu ruinieren.

Folgende Routiene soll jedes Wort welche zwischen > und < steht also Start und End-HTML-Tag und dem Muster entspricht ersetzen (aktuell einfach in Kursivschrift) und dabei die Schreibweise erhalten. Nur stehe ich mit meiner Routiene vor einem weissen Bildschirm ohne Fehlerausgabe, der Fehler liegt aber bei preg_replace

Code:
function contentconvert($puffer) {
if(isset($GLOBALS["ndaten"]) and isset($_SESSION["newsmuster"])) {
		if($muster = explode(" ",$_SESSION["newsmuster"])) {
			$m = implode($muster,"|");
			$puffer = preg_replace('>$('.$m.'\i)$<','<i>\1</i>',$puffer);
		}
	}
	return $puffer;
}

Wie muss der Code geändert werden damit ich mein Ziel erreiche? :confused:
 
Hi,

das Problem liegt vermutlich daran, dass du keinen "Delimiter" für den RegEx angegeben hast. Genaueres über die preg_replace Funktion findest du auf php.net.

Wenn du also einen Delimiter verwendest, dann sollte dein RegEx so aussehen:
Code:
/>$('.$m.'\i)$</
In diesem Falle ist der "/" dein Delimiter.

Ausserdem kommt mr das "\i" in deinem RegEx falsch vor, evtl meckert da php dass es die Escape-Sequenz nicht kennt.

Setze bitte auf alle Fälle mal ein "error_reporting(E_ALL);" vor deinem preg_replace()-Aufruf, dann sollten auch Fehlermeldungen ausgegeben werden.

Einen kleinen Tip hier noch am Rande: Jage deine Suchbegriffe noch einzeln durch die preg_quote() Funktion bevor du den RegEx zusammenbaust, damit auch nichts schief gehen kann falls der Benutzer nach einem "|" oder einem "/" sucht ;)

Gruß
BK
 
Zuletzt bearbeitet:
Hmm, jetzt gibts wenigstes keinen weissen Bildschirm, aber ersetzt wird auch nichts, der HTML-Code bleibt der selbe egal ob mit oder ohne \i was soviel ich weiss bedeutet das das die Goß/Kleinscheibung nicht beachtet wird, das Muster selbst ist ok. Und E_ALL wirkte bei meinem Hoster noch nie, wird ignoriert.

Ich gebe zu ich habe keine Ahnung von regularen Ausdrücken, arbeite sehr selten damit :(

Wo liegt der Fehler? Ist das $ im Ausdruck überhaupt richtig?

Code:
function contentconvert($puffer) {
         if(isset($GLOBALS["ndaten"]) and isset($_SESSION["newsmuster"])) {
		if($muster = explode(" ",$_SESSION["newsmuster"])) {
			for($t=0;$t<count($muster);$t++) {
				$muster[$t] = preg_quote($muster[$t]);
			}
			$m = implode($muster,"|");
			error_log(date("y-m-d H:i:s")." .$m. ".__FILE__."\r\n",0);
			$puffer = preg_replace('/>$('.$m.'\i)$</','<i>\1</i>',$puffer);
		}
	}
	return $puffer;
}
 
Zuletzt bearbeitet:
Versuch doch mal diese Kombination:
PHP:
error_reporting(E_ALL);
ini_set("display_errors",1);

Kann es sein das ini_set("display_errors",1); eine Fehlerausgabe auf den Monitor bewirkt? Das halte ich für einen Sicherheitsfehler (Vor allen bei bis zu 6000 Besuchern am Tag!), normalerweise werden die Fehler in cgi_error.log geschrieben, aber beim jetzigen Skript folgt keine Ausgabe das war schonmal anders. Nach letzten Stand werden nur uninitialisierte Variablen, POST und GET-Attacken und nicht gefundene Funktionen aufgelistet wenn mal ein Fehler auftreten sollte.

Jetzt sind wir vom Thema abgekommen, zurück zum regulären Ausdruck:

Also ich möchte das 'muster' durch <i>Muster</i> ersetzt wird aber nur wenn das Muster zwischen > und < steht um den HTML-Code nicht zu zerstören, wie:

HTML:
muster<p>Das ist ein Muster mit beliebigen Text <img src="muster" width="250"> und nochmal muster</p>muster

Soll durch
HTML:
muster<p>Das ist ein <i>Muster</i> mit beliebigen Text <img src="muster" width="250"> und nochmal <i>muster</i></p>muster

ergänzt werden, Groß/Kleinschreibung bei der Suche soll nicht beachtet werden aber bei der Ausgabe zwischen <i> und </i> übernommen werden.
 
Kann es sein das ini_set("display_errors",1); eine Fehlerausgabe auf den Monitor bewirkt? Das halte ich für einen Sicherheitsfehler (Vor allen bei bis zu 6000 Besuchern am Tag!)

Richtig, wenn man die Seite öffentlich macht, sollte man das natürlich nicht tun. Solange du aber am Testen bist (wovon ich gerade mal ausgegangen bin), kann man es ja ruhig einstellen :)
 
[...]
\i was soviel ich weiss bedeutet das das die Goß/Kleinscheibung nicht beachtet wird
[...]

Ja, der i-Modifikator gibt an, dass es case-insenstive suchen soll. Aber die Modifikatoren kommen nach dem Delimiter, nicht einfach mitten im RegEx.

Desweiteren fällt mir gerade auf, dass dein "$" im Regex Probleme machen kann, da dies normalerweise das Zeilenende markiert.
Nach deiner "Wunsch-Beschreibung" würde ich mal folgenden Regex ausprobieren:

Code:
/>(' . $m . ')</i

Falls der immer noch nicht funktioniert, kannst du mal die > und < escapen (einfach nen Backslash davor setzen).

Gruß
BK
 
Ja, der i-Modifikator gibt an, dass es case-insenstive suchen soll. Aber die Modifikatoren kommen nach dem Delimiter, nicht einfach mitten im RegEx.

Desweiteren fällt mir gerade auf, dass dein "$" im Regex Probleme machen kann, da dies normalerweise das Zeilenende markiert.
Nach deiner "Wunsch-Beschreibung" würde ich mal folgenden Regex ausprobieren:

Code:
/>(' . $m . ')</i

Falls der immer noch nicht funktioniert, kannst du mal die > und < escapen (einfach nen Backslash davor setzen).

Gruß
BK

Nein geht nicht, auch nicht mit Backslash, es erfolgt keine Ersetzung.

Code:
'/\>('.$m.')\</i'

Übrigens geht es um Folgene Seite Edelmetall-News
damit ihr euch mal den HTML-Code anschauen könnt, ersetzt wird nur in der Nachricht aber nicht in der Übersicht. Sucht am besten einfach nach 'Mai' oder 'mai', Nochmal zur Erinnerung: es wird die komplette HTML-SEite durch sucht und ersetzt.
 
Zuletzt bearbeitet:
Keiner eine Idee? :(

der Code sieht jetzt so aus:

Liegt es vieleicht an den HTML-Verschachtelungen das es nicht Funktioniert?

Code:
function contentconvert($puffer) {
         if(isset($GLOBALS["ndaten"]) and isset($_SESSION["newsmuster"])) {
		if($muster = explode(" ",$_SESSION["newsmuster"])) {
			for($t=0;$t<count($muster);$t++) {
				$muster[$t] = preg_quote($muster[$t]);
			}
			$m = implode($muster,"|");
			$puffer = preg_replace('/\>('.$m.')\</i','<i>\1</i>',$puffer);
		}
	}
	return $puffer;
}

Ich bin jetzt soweit gekommen:

Code:
$puffer = preg_replace('/\>(.*)('.$m.')(.*)\</i','>\1<span style="background-color: #FDFD00;">\2</span>\3<',$puffer);

Nur leider werden jetzt die Links Zerstört wenn das Muster darin auftritt. Was kann man dagegen Tun?

21:12 Uhr
Wie muss der obere Ausdruck aussehen, damit er nur von der Start und End zeichenkette "[start]" bis "[ende]" sucht und ersetzt? Dann würde die Links nicht beachtet werden.

22:02 Uhr
Problem durch ein anderes Forum gelöst:

Code:
$puffer = preg_replace("/(?!(?:[^<]+>|[^>]+<\/(a|h[1-9])>))(".$m.")/i",'\1<span style="background-color: #FDFD00;">\2</span>\3',$puffer);
 
Zuletzt bearbeitet:
Zurück