Ich möchte eine Version von str_replace()
die nur das erste Vorkommen von $search
en el $subject
. Gibt es eine einfache Lösung für dieses Problem, oder brauche ich eine komplizierte Lösung?
Antworten
Zu viele Anzeigen?Es gibt keine Version davon, aber die Lösung ist überhaupt nicht umständlich.
$pos = strpos($haystack, $needle);
if ($pos !== false) {
$newstring = substr_replace($haystack, $replace, $pos, strlen($needle));
}
Das ist ziemlich einfach und erspart die Leistungseinbußen von regulären Ausdrücken.
Bonus: Wenn Sie Folgendes ersetzen möchten zuletzt Auftreten, verwenden Sie einfach strrpos
anstelle von strpos
.
Kann durchgeführt werden mit preg_replace :
function str_replace_first($search, $replace, $subject)
{
$search = '/'.preg_quote($search, '/').'/';
return preg_replace($search, $replace, $subject, 1);
}
echo str_replace_first('abc', '123', 'abcdef abcdef abcdef');
// outputs '123def abcdef abcdef'
Der Zauber liegt im optionalen vierten Parameter [Limit]. Aus der Dokumentation:
[Limit] - Die maximal möglichen Ersetzungen für jedes Muster in jeder Betreff-Zeichenkette. Der Standardwert ist -1 (keine Grenze).
Allerdings, siehe Zombats Antwort für eine effizientere Methode (etwa 3-4x schneller).
Edit: Beide Antworten wurden aktualisiert und sind nun korrekt. Ich lasse die Antwort stehen, da die Zeitangaben der Funktion immer noch nützlich sind.
Die Antworten von 'zombat' und 'too much php' sind leider nicht richtig. Dies ist eine Überarbeitung der Antwort, die zombat gepostet hat (da ich nicht genug Ansehen habe, um einen Kommentar zu schreiben):
$pos = strpos($haystack,$needle);
if ($pos !== false) {
$newstring = substr_replace($haystack,$replace,$pos,strlen($needle));
}
Beachten Sie strlen($needle) anstelle von strlen($replace). Das Beispiel von Zombat funktioniert nur korrekt, wenn needle und replace die gleiche Länge haben.
Hier ist die gleiche Funktionalität in einer Funktion mit der gleichen Signatur wie PHPs str_replace:
function str_replace_first($search, $replace, $subject) {
$pos = strpos($subject, $search);
if ($pos !== false) {
return substr_replace($subject, $replace, $pos, strlen($search));
}
return $subject;
}
Dies ist die revidierte Antwort von "zu viel php":
implode($replace, explode($search, $subject, 2));
Beachten Sie die 2 am Ende anstelle der 1. Oder im Funktionsformat:
function str_replace_first($search, $replace, $subject) {
return implode($replace, explode($search, $subject, 2));
}
Ich habe die beiden Funktionen gemessen, und die erste ist doppelt so schnell, wenn keine Übereinstimmung gefunden wird. Sie sind gleich schnell, wenn eine Übereinstimmung gefunden wird.
Ich wollte wissen, welches das schnellste ist, und habe alle getestet.
Nachfolgend finden Sie:
- Eine umfassende Liste aller Funktionen, die zu dieser Seite beigetragen haben
- Benchmark-Tests für jede Lösung (durchschnittliche Ausführungszeit über 10.000 Läufe)
- Links zu jeder Antwort (für den vollständigen Code)
Alle Funktionen wurden mit den gleichen Einstellungen getestet:
$string = 'OOO.OOO.OOO.S';
$search = 'OOO';
$replace = 'B';
Funktionen, die nur ersetzen die erste Auftreten einer Zeichenkette innerhalb einer Zeichenkette:
-
substr_replace($string, $replace, 0, strlen($search));
[CONTRIBUTED BY] => zombat [OOO.OOO.OOO.S] => B.OOO.OOO.S [AVERAGE TIME] => 0.0000062883 [SLOWER BY] => FASTEST
-
replace_first($search, $replace, $string);
[CONTRIBUTED BY] => too much php [OOO.OOO.OOO.S] => B.OOO.OOO.S [AVERAGE TIME] => 0.0000073902 [SLOWER BY] => 17.52%
-
preg_replace($search, $replace, $string, 1);
[CONTRIBUTED BY] => karim79 [OOO.OOO.OOO.S] => B.OOO.OOO.S [AVERAGE TIME] => 0.0000077519 [SLOWER BY] => 23.27%
-
str_replace_once($search, $replace, $string);
[CONTRIBUTED BY] => happyhardik [OOO.OOO.OOO.S] => B.OOO.OOO.S [AVERAGE TIME] => 0.0000082286 [SLOWER BY] => 30.86%
-
str_replace_limit($search, $replace, $string, $count, 1);
[CONTRIBUTED BY] => bfrohs - expanded renocor [OOO.OOO.OOO.S] => B.OOO.OOO.S [AVERAGE TIME] => 0.0000083342 [SLOWER BY] => 32.54%
-
str_replace_limit($search, $replace, $string, 1);
[CONTRIBUTED BY] => renocor [OOO.OOO.OOO.S] => B.OOO.OOO.S [AVERAGE TIME] => 0.0000093116 [SLOWER BY] => 48.08%
-
str_replace_limit($string, $search, $replace, 1, 0);
[CONTRIBUTED BY] => jayoaK [OOO.OOO.OOO.S] => B.OOO.OOO.S [AVERAGE TIME] => 0.0000093862 [SLOWER BY] => 49.26%
Funktionen, die nur ersetzen die letzte Auftreten einer Zeichenkette innerhalb einer Zeichenkette:
-
substr_replace($string, $replace, strrpos($string, $search), strlen($search));
[CONTRIBUTED BY] => oLinkSoftware - modified zombat [OOO.OOO.OOO.S] => OOO.OOO.B.S [AVERAGE TIME] => 0.0000068083 [SLOWER BY] => FASTEST
-
strrev(implode(strrev($replace), explode(strrev($search), strrev($string), 2)));
[CONTRIBUTED BY] => oLinkSoftware [OOO.OOO.OOO.S] => OOO.OOO.B.S [AVERAGE TIME] => 0.0000084460 [SLOWER BY] => 24.05%
Leider ist mir keine PHP-Funktion bekannt, die das kann.
Sie können Ihre eigene Rolle relativ leicht auf diese Weise drehen:
function replace_first($find, $replace, $subject) {
// stolen from the comments at PHP.net/str_replace
// Splits $subject into an array of 2 items by $find,
// and then joins the array with $replace
return implode($replace, explode($find, $subject, 2));
}
- See previous answers
- Weitere Antworten anzeigen