Seite 1 von 3

str_replace nur einmal ausführen

Verfasst: 09.02.2010, 17:27
von w3news
Hallo,

vielleicht stehe ich ja auf der Leitung, aber kann mir jemand einen Tipp geben wie ich einen String in einem Text ersetzen kann, dies aber nur einmal?

Also ich habe einen Text:
Dies ist ein Test. Den Test sollte man immer machen.
Jetzt soll das Wort Test ersetzt werden, aber allerdings nur einmal, wenn es geht das letzte Test, dass erste wäre aber auch in Ordnung.

Danke für jeden Tipp.

Verfasst:
von

Verfasst: 09.02.2010, 17:42
von w3news
So, habs mal mit der preg_replace probiert geht aber auch nicht so wirklich:

Code: Alles auswählen

$limit=1;
$count=1;
$url=preg_replace('Test', 'Test2', $url, $limit, $count);
Fehlermeldung:
Delimiter must not be alphanumeric or backslash...

Verfasst: 09.02.2010, 17:44
von Synonym
Hm, nur mal so in den Raum geworfen

Ich würde mit strrpos die letzte Position der gesuchten Zeichenkette suchen und denn mit substr_replace ab der Position ersetzen.

Gibt aber sicherlich auch andere Wege

Verfasst:
von
SEO Consulting bei ABAKUS Internet Marketing
Erfahrung seit 2002
  • persönliche Betreuung
  • individuelle Beratung
  • kompetente Umsetzung

Jetzt anfragen: 0511 / 300325-0.


Verfasst: 09.02.2010, 17:47
von ishmael
Die Funktion preg_replace() hat einen $limit Parameter. Um den letzen Wert zu ersetzen könnte man den String und den regulären Ausdruck mit strrev() umdrehen und anschließend wieder zurückdrehen.

Edit: preg_replace arbeitet mit pear regular expressions

Das Pattern sähe z.B. so aus:

Code: Alles auswählen

/Test/

Verfasst: 09.02.2010, 17:50
von Synonym
Nachtrag:

Bei Deinem Code oben ist das "$count=1; " der Fehler. Über "$count" liefert die Funktion die Anzahl der ersetzen Stellen zurück, da darfst Du selbst keinen Wert vorgeben.

Verfasst: 09.02.2010, 17:53
von ishmael
Die Fehlermeldung bezieht sich auf den fehlerhaften regulären Ausdruck. Siehe Edit in meinem Post.

Unabhängig davon ist die Idee mit strpos() und substr_replace wohl am effektivsten.

Verfasst: 09.02.2010, 18:10
von w3news
Danke schon mal, klappt auch, aber nicht ganz:
$url="Dies ist ein Test. Den Test sollte man immer machen.";
$suchmuster="Test";
$limit=strrpos($url,$suchmuster);
$ersetzung="Test2";
$url=substr_replace($suchmuster, $ersetzung, $url, $limit);
echo "$url";
Jetzt kommt beim echo nur "Test2" raus, nicht aber der Rest vom Text.

Verfasst: 09.02.2010, 18:32
von SloMo
Hast Du Dir die Doku von substr_replace überhaupt angesehen?

So müsste es gehen (nicht getestet):

Code: Alles auswählen

$url="Dies ist ein Test. Den Test sollte man immer machen.";
$suchmuster="Test";
$start = strpos($url, $suchmuster);
$length = strlen($suchmuster);
$ersetzung="Test2";
$url=substr_replace($url, $ersetzung, $start, $length);
echo "$url";

Verfasst: 09.02.2010, 18:43
von w3news
Gelesen schon, aber das habe ich doch glatt ignoriert, danke euch jetzt funktioniert es so wie es gewünscht ist!

Verfasst: 10.02.2010, 03:06
von mgutt
preg_replace() dürfte in dem Fall genauso schnell sein

Code: Alles auswählen

$url = preg_replace('/Test/', 'Test2', $url, 1);
Wenn nicht sogar schneller, wenn man die ganzen Vars so sieht, die hier unnötigerweise gesetzt werden :P

Verfasst: 10.02.2010, 10:50
von SloMo
Hey Marc, guter Einwand! Ich hatte eigentlich nur den Code korrigiert, ohne überhaupt auf Performance zu achten. Trotzdem hatte mein Bauchgefühl mir gesagt, dass performance-mäßig fast alles besser als preg_replace() ist.
mgutt hat geschrieben:$url = preg_replace('/Test/', 'Test2', $url, 1);
Du darfst natürlich keine Variablen entfernen, die tatsächlich gebraucht werden. Die preg_replace() wird ja kaum mit Konstanten gefüttert. Der wesentliche Unterschied beider Varianten besteht also nicht in der Anzahl der Variablen, sondern in der Anzahl der Aufrufe (bzw. in der Komplexität des Codes dahinter).

Aus Interesse habe ich mal die Probe gemacht. Es tritt als Solist das Universalgenie preg_replace() gegen das Spezialisten-Trio strpos(), strlen(), substr_replace() an. Beide Teams dürfen 10.000.000x zeigen, wer schneller ist.

Code: Alles auswählen

<?php

function microtime_float&#40;&#41;
&#123;
	list&#40;$usec, $sec&#41; = explode&#40;" ", microtime&#40;&#41;&#41;;
	return &#40;&#40;float&#41;$usec + &#40;float&#41;$sec&#41;;
&#125;

$url="Dies ist ein Test. Den Test sollte man immer machen.";
$suchmuster = "Test";
$ersetzung = "Test2";
$i=0;

$preg_start = microtime_float&#40;&#41;;
&#123;
	// *** PREG_REPLACE ***
	for&#40;$i; $i<10000000; $i++&#41; &#123;
		$preg_result = preg_replace&#40;"/&#123;$suchmuster&#125;/", $ersetzung, $url, 1&#41;;
	&#125;
&#125;
$preg_end = microtime_float&#40;&#41;;

$i=0;

$substr_start = microtime_float&#40;&#41;;
&#123;
	// *** SUBSTR_REPLACE ***
	for&#40;$i; $i<10000000; $i++&#41; &#123;
		$start = strpos&#40;$url, $suchmuster&#41;;
		$length = strlen&#40;$suchmuster&#41;;
		$substr_result = substr_replace&#40;$url, $ersetzung, $start, $length&#41;;
	&#125;
&#125;
$substr_end = microtime_float&#40;&#41;;

echo "PREG&#58; &#123;$preg_result&#125; &#40;".round&#40;$preg_end - $preg_start, 2&#41;."s&#41;<br>";
echo "SUBSTR&#58; &#123;$substr_result&#125; &#40;".round&#40;$substr_end - $substr_start, 2&#41;."s&#41;<br>";
Ausgabe:
PREG: Dies ist ein Test2. Den Test sollte man immer machen. (17.82s)
SUBSTR: Dies ist ein Test2. Den Test sollte man immer machen. (11.43s)

Fazit:
Die PREG-Variante ist gut 50 Prozent langsamer! :P ;)

Verfasst: 10.02.2010, 10:53
von Synonym
Und wenn man nun nicht immer strpos(), sondern das anfangs geschriebene strrpos() verwendet, dann hat man auch den letzten Wert als Ersatz, so wie es eigentlich gewünscht war. Das preg_replace kann nämlich auch nur am Anfang beginnen. 8)

Verfasst: 10.02.2010, 11:07
von SloMo
Synonym hat geschrieben:Und wenn man nun nicht immer strpos(), sondern das anfangs geschriebene strrpos() verwendet, dann hat man auch den letzten Wert als Ersatz, so wie es eigentlich gewünscht war. Das preg_replace kann nämlich auch nur am Anfang beginnen. 8)
Na und? Dann macht man es so:

Code: Alles auswählen

$preg_result = preg_replace&#40;"/&#40;.*&#41;&#123;$suchmuster&#125;/", "\$1$ersetzung", $url, 1&#41;;
Der obige Code (mit einigen Anpassungen) ergibt dann nach nur 1.000.000 Durchläufen pro Verfahren:

PREG: Dies ist ein Test. Den Test sollte man immer machen. Denn ohne Test2 geht es nicht. (7.31s)
SUBSTR: Dies ist ein Test. Den Test sollte man immer machen. Denn ohne Test2 geht es nicht. (1.39s)

In diesem Fall ist preg_replace() um ca. Faktor 5 langsamer.

Verfasst: 10.02.2010, 11:29
von Synonym
In welcher Beziehung stehen die beiden Aussagen

"Na und? Dann macht man es so: "
und
"In diesem Fall ist preg_replace() um ca. Faktor 5 langsamer."

Eben deshalb hatte ich ja kein preg_replace genommen. :wink:

Verfasst: 10.02.2010, 11:35
von SloMo
Ist doch überhaupt nicht schlimm, dass Du dachtest, dass preg_replace() nicht das letzte Vorkommen ersetzen kann. ;)