Ich möchte eine Version davon str_replace()
, die nur das erste Auftreten von $search
in der ersetzt $subject
. Gibt es eine einfache Lösung dafür oder brauche ich eine hackige Lösung?
Ich möchte eine Version davon str_replace()
, die nur das erste Auftreten von $search
in der ersetzt $subject
. Gibt es eine einfache Lösung dafür oder brauche ich eine hackige Lösung?
Antworten:
Kann mit preg_replace durchgeführt werden :
function str_replace_first($from, $to, $content)
{
$from = '/'.preg_quote($from, '/').'/';
return preg_replace($from, $to, $content, 1);
}
echo str_replace_first('abc', '123', 'abcdef abcdef abcdef');
// outputs '123def abcdef abcdef'
Die Magie liegt im optionalen vierten Parameter [Limit]. Aus der Dokumentation:
[Limit] - Die maximal mögliche Ersetzung für jedes Muster in jeder Betreffzeichenfolge. Der Standardwert ist -1 (keine Begrenzung).
Obwohl finden Sie zombat Antwort für eine effizientere Methode (grob, 3-4x schneller).
preg_quote
? Zum Beispiel befürchtet @ThomasRedstone, dass das Trennzeichen /
gefährlich sein könnte, wenn es in angezeigt wird $from
, aber zum Glück nicht: Es wird aufgrund des preg_quote
zweiten Parameters ordnungsgemäß maskiert (das kann man leicht testen). Ich würde gerne etwas über bestimmte Probleme erfahren (die in meinem Buch schwerwiegende PCRE-Sicherheitslücken darstellen würden).
Es gibt keine Version davon, aber die Lösung ist überhaupt nicht hackig.
$pos = strpos($haystack, $needle);
if ($pos !== false) {
$newstring = substr_replace($haystack, $replace, $pos, strlen($needle));
}
Ziemlich einfach und spart die Leistungseinbußen bei regulären Ausdrücken.
Bonus: Wenn Sie das letzte Vorkommen ersetzen möchten , verwenden Sie es einfach strrpos
anstelle von strpos
.
substr_replace
es sich aufgrund aller Parameter um eine etwas unhandliche Funktion handelt, besteht das eigentliche Problem darin, dass die Manipulation von Zeichenfolgen durch Zahlen manchmal nur schwierig ist. Sie müssen darauf achten, die richtige Variable / den richtigen Offset an die Funktionen zu übergeben. Ich würde sogar so weit gehen zu sagen, dass der obige Code der einfachste und für mich logischste Ansatz ist.
Bearbeiten: Beide Antworten wurden aktualisiert und sind jetzt korrekt. Ich werde die Antwort hinterlassen, da die Funktionszeiten immer noch nützlich sind.
Die Antworten von 'zombat' und 'too much php' sind leider nicht korrekt. Dies ist eine Überarbeitung der Antwort von zombat (da ich nicht genug Ruf habe, um einen Kommentar zu schreiben):
$pos = strpos($haystack,$needle);
if ($pos !== false) {
$newstring = substr_replace($haystack,$replace,$pos,strlen($needle));
}
Beachten Sie die Strlen ($ Nadel) anstelle von Strlen ($ Ersetzen). Das Beispiel von Zombat funktioniert nur dann korrekt, wenn Nadel und Ersatz dieselbe Länge haben.
Hier ist die gleiche Funktionalität in einer Funktion mit der gleichen Signatur wie PHPs eigener 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 überarbeitete Antwort von 'zu viel PHP':
implode($replace, explode($search, $subject, 2));
Beachten Sie die 2 am Ende anstelle von 1. Oder im Funktionsformat:
function str_replace_first($search, $replace, $subject) {
return implode($replace, explode($search, $subject, 2));
}
Ich habe die beiden Funktionen zeitlich festgelegt und die erste ist doppelt so schnell, wenn keine Übereinstimmung gefunden wird. Sie haben die gleiche Geschwindigkeit, wenn eine Übereinstimmung gefunden wird.
stripos()
zur Rettung :-)
Ich habe mich gefragt, welches das schnellste ist, also habe ich sie alle getestet.
Unten finden Sie:
Alle Funktionen wurden mit den gleichen Einstellungen getestet:
$string = 'OOO.OOO.OOO.S';
$search = 'OOO';
$replace = 'B';
Funktionen, die nur das erste Auftreten einer Zeichenfolge innerhalb einer Zeichenfolge ersetzen :
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 das letzte Vorkommen einer Zeichenfolge innerhalb einer Zeichenfolge ersetzen :
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%
substr_replace()
das Ergebnis gewonnen wird, ist einfach; weil es eine interne Funktion ist. Zwei interne und benutzerdefinierte Funktionen, die dasselbe tun, unterscheiden sich in der Leistung, da die interne Funktion in niedrigeren Ebenen ausgeführt wird. Warum also nicht preg_match()
? Reguläre Ausdrücke sind fast langsamer als jede interne String-Manipulationsfunktion, da sie mehrmals in einem String suchen.
substr_replace($string, $replace, 0, strlen($search));
) nicht nur diese Statik geschrieben hat 0
. Ein Teil der Faltung von Nicht-Regex-Lösungen besteht darin, dass sie den Ausgangspunkt "finden" müssen, bevor sie wissen, wo sie ersetzt werden müssen.
Leider kenne ich keine PHP-Funktion, die dies kann.
Sie können Ihre eigenen ziemlich einfach so rollen:
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));
}
return implode($replace, explode($find, $subject, $limit+1));
für benutzerdefinierte
Ich habe diese kleine Funktion erstellt, die String für String (Groß- und Kleinschreibung beachten) durch Limit ersetzt, ohne dass Regexp erforderlich ist. Es funktioniert gut.
function str_replace_limit($search, $replace, $string, $limit = 1) {
$pos = strpos($string, $search);
if ($pos === false) {
return $string;
}
$searchLen = strlen($search);
for ($i = 0; $i < $limit; $i++) {
$string = substr_replace($string, $replace, $pos, $searchLen);
$pos = strpos($string, $search);
if ($pos === false) {
break;
}
}
return $string;
}
Anwendungsbeispiel:
$search = 'foo';
$replace = 'bar';
$string = 'foo wizard makes foo brew for evil foo and jack';
$limit = 2;
$replaced = str_replace_limit($search, $replace, $string, $limit);
echo $replaced;
// bar wizard makes bar brew for evil foo and jack
===false
würde is_bool(
, als expliziter zu sein - ich gebe diesen Daumen auf, nur weil er den RegExp-Wahnsinn vermieden hat ! ... und gleichzeitig funktioniert es und saubere Lösung ...
preg_
Lösung zu bevorzugen, ist kein Wahnsinn, sondern eine persönliche Präferenz. return preg_replace('/'.preg_quote($search, '/').'/', $replace, $content, 1);
ist ziemlich einfach zu lesen für Leute, die keine Angst vor Regex haben. Benötigen Sie eine Suche ohne Berücksichtigung der Groß- und Kleinschreibung? Fügen Sie i
nach dem Ende Muster - Begrenzung. Benötigen Sie Unicode / Multibyte-Unterstützung? Fügen Sie u
nach dem Ende Muster - Begrenzung. Benötigen Sie Unterstützung für Wortgrenzen? Fügen Sie \b
auf beiden Seiten Ihrer Suchzeichenfolge hinzu. Wenn Sie keinen regulären Ausdruck wünschen, verwenden Sie keinen regulären Ausdruck. Pferde für Kurse, aber sicher kein Wahnsinn.
Am einfachsten wäre es, reguläre Ausdrücke zu verwenden.
Die andere Möglichkeit besteht darin, die Position des Strings mit strpos () und dann mit substr_replace () zu ermitteln.
Aber ich würde mich wirklich für die RegExp entscheiden.
function str_replace_once($search, $replace, $subject) {
$pos = strpos($subject, $search);
if ($pos === false) {
return $subject;
}
return substr($subject, 0, $pos) . $replace . substr($subject, $pos + strlen($search));
}
=> CODE WURDE ÜBERARBEITET, daher sollten einige Kommentare zu alt sein
Und vielen Dank an alle, die mir geholfen haben, das zu verbessern
Irgendwelche BUG, bitte teilen Sie mir mit; Ich werde das gleich danach beheben
Also los geht's für:
Ersetzen des ersten 'o' durch 'ea' zum Beispiel:
$s='I love you';
$s=str_replace_first('o','ea',$s);
echo $s;
//output: I leave you
Die Funktion:
function str_replace_first($a,$b,$s)
{
$w=strpos($s,$a);
if($w===false)return $s;
return substr($s,0,$w).$b.substr($s,$w+strlen($a));
}
substr($where,$b+strlen($this))
nicht sein substr($where,$b+1)
. Und ich denke das substr_replace
ist schneller.
$string = 'this is my world, not my world';
$find = 'world';
$replace = 'farm';
$result = preg_replace("/$find/",$replace,$string,1);
echo $result;
preg_quote
von ausführen, $find
bevor Sie es als Ausdruck verwenden.
preg_quote()
. Diese späte doppelte Antwort kann sicher von der Seite gelöscht werden, da ihre Ratschläge von der früheren und höher bewerteten akzeptierten Antwort bereitgestellt werden.
Um die Antwort von @ renocor zu erweitern , habe ich eine Funktion geschrieben, die zu 100% abwärtskompatibel ist str_replace()
. Das heißt, Sie ersetzen können alle Vorkommen str_replace()
mit , str_replace_limit()
ohne etwas durcheinander, auch die Verwendung von Arrays für die $search
, $replace
und / oder $subject
.
Die Funktion könnte vollständig in sich geschlossen sein, wenn Sie den Funktionsaufruf durch ersetzen möchten ($string===strval(intval(strval($string))))
, aber ich würde dagegen empfehlen, da dies valid_integer()
eine ziemlich nützliche Funktion ist, wenn Sie Ganzzahlen verwenden, die als Zeichenfolgen bereitgestellt werden.
Hinweis: Wann immer möglich, str_replace_limit()
wird str_replace()
stattdessen verwendet, sodass alle Anrufe an str_replace()
durch ersetzt werden können, str_replace_limit()
ohne sich um einen Leistungseinbruch sorgen zu müssen.
<?php
$search = 'a';
$replace = 'b';
$subject = 'abcabc';
$limit = -1; // No limit
$new_string = str_replace_limit($search, $replace, $subject, $count, $limit);
echo $count.' replacements -- '.$new_string;
2 Ersetzungen - bbcbbc
$limit = 1; // Limit of 1
$new_string = str_replace_limit($search, $replace, $subject, $count, $limit);
echo $count.' replacements -- '.$new_string;
1 Ersatz - bbcabc
$limit = 10; // Limit of 10
$new_string = str_replace_limit($search, $replace, $subject, $count, $limit);
echo $count.' replacements -- '.$new_string;
2 Ersetzungen - bbcbbc
<?php
/**
* Checks if $string is a valid integer. Integers provided as strings (e.g. '2' vs 2)
* are also supported.
* @param mixed $string
* @return bool Returns boolean TRUE if string is a valid integer, or FALSE if it is not
*/
function valid_integer($string){
// 1. Cast as string (in case integer is provided)
// 1. Convert the string to an integer and back to a string
// 2. Check if identical (note: 'identical', NOT just 'equal')
// Note: TRUE, FALSE, and NULL $string values all return FALSE
$string = strval($string);
return ($string===strval(intval($string)));
}
/**
* Replace $limit occurences of the search string with the replacement string
* @param mixed $search The value being searched for, otherwise known as the needle. An
* array may be used to designate multiple needles.
* @param mixed $replace The replacement value that replaces found search values. An
* array may be used to designate multiple replacements.
* @param mixed $subject The string or array being searched and replaced on, otherwise
* known as the haystack. If subject is an array, then the search and replace is
* performed with every entry of subject, and the return value is an array as well.
* @param string $count If passed, this will be set to the number of replacements
* performed.
* @param int $limit The maximum possible replacements for each pattern in each subject
* string. Defaults to -1 (no limit).
* @return string This function returns a string with the replaced values.
*/
function str_replace_limit(
$search,
$replace,
$subject,
&$count,
$limit = -1
){
// Set some defaults
$count = 0;
// Invalid $limit provided. Throw a warning.
if(!valid_integer($limit)){
$backtrace = debug_backtrace();
trigger_error('Invalid $limit `'.$limit.'` provided to '.__function__.'() in '.
'`'.$backtrace[0]['file'].'` on line '.$backtrace[0]['line'].'. Expecting an '.
'integer', E_USER_WARNING);
return $subject;
}
// Invalid $limit provided. Throw a warning.
if($limit<-1){
$backtrace = debug_backtrace();
trigger_error('Invalid $limit `'.$limit.'` provided to '.__function__.'() in '.
'`'.$backtrace[0]['file'].'` on line '.$backtrace[0]['line'].'. Expecting -1 or '.
'a positive integer', E_USER_WARNING);
return $subject;
}
// No replacements necessary. Throw a notice as this was most likely not the intended
// use. And, if it was (e.g. part of a loop, setting $limit dynamically), it can be
// worked around by simply checking to see if $limit===0, and if it does, skip the
// function call (and set $count to 0, if applicable).
if($limit===0){
$backtrace = debug_backtrace();
trigger_error('Invalid $limit `'.$limit.'` provided to '.__function__.'() in '.
'`'.$backtrace[0]['file'].'` on line '.$backtrace[0]['line'].'. Expecting -1 or '.
'a positive integer', E_USER_NOTICE);
return $subject;
}
// Use str_replace() whenever possible (for performance reasons)
if($limit===-1){
return str_replace($search, $replace, $subject, $count);
}
if(is_array($subject)){
// Loop through $subject values and call this function for each one.
foreach($subject as $key => $this_subject){
// Skip values that are arrays (to match str_replace()).
if(!is_array($this_subject)){
// Call this function again for
$this_function = __FUNCTION__;
$subject[$key] = $this_function(
$search,
$replace,
$this_subject,
$this_count,
$limit
);
// Adjust $count
$count += $this_count;
// Adjust $limit, if not -1
if($limit!=-1){
$limit -= $this_count;
}
// Reached $limit, return $subject
if($limit===0){
return $subject;
}
}
}
return $subject;
} elseif(is_array($search)){
// Only treat $replace as an array if $search is also an array (to match str_replace())
// Clear keys of $search (to match str_replace()).
$search = array_values($search);
// Clear keys of $replace, if applicable (to match str_replace()).
if(is_array($replace)){
$replace = array_values($replace);
}
// Loop through $search array.
foreach($search as $key => $this_search){
// Don't support multi-dimensional arrays (to match str_replace()).
$this_search = strval($this_search);
// If $replace is an array, use the value of $replace[$key] as the replacement. If
// $replace[$key] doesn't exist, just an empty string (to match str_replace()).
if(is_array($replace)){
if(array_key_exists($key, $replace)){
$this_replace = strval($replace[$key]);
} else {
$this_replace = '';
}
} else {
$this_replace = strval($replace);
}
// Call this function again for
$this_function = __FUNCTION__;
$subject = $this_function(
$this_search,
$this_replace,
$subject,
$this_count,
$limit
);
// Adjust $count
$count += $this_count;
// Adjust $limit, if not -1
if($limit!=-1){
$limit -= $this_count;
}
// Reached $limit, return $subject
if($limit===0){
return $subject;
}
}
return $subject;
} else {
$search = strval($search);
$replace = strval($replace);
// Get position of first $search
$pos = strpos($subject, $search);
// Return $subject if $search cannot be found
if($pos===false){
return $subject;
}
// Get length of $search, to make proper replacement later on
$search_len = strlen($search);
// Loop until $search can no longer be found, or $limit is reached
for($i=0;(($i<$limit)||($limit===-1));$i++){
// Replace
$subject = substr_replace($subject, $replace, $pos, $search_len);
// Increase $count
$count++;
// Get location of next $search
$pos = strpos($subject, $search);
// Break out of loop if $needle
if($pos===false){
break;
}
}
// Return new $subject
return $subject;
}
}
E_USER_WARNING
gesamten Gebäude , das eine ist Warnung , nicht ein Fehler . Die Rückverfolgung ist äußerst nützlich, um herauszufinden, welcher Code die ungültigen Daten überhaupt an die Funktion weitergibt (was unbedingt erforderlich ist, um Fehler in der Produktion aufzuspüren). Wie bei der Rückkehr $subject
statt false
/ null
oder einen Fehler zu werfen, die einfach eine persönliche Entscheidung für meinen Anwendungsfall war. Um mit str_replace()
der Funktionalität übereinzustimmen, ist es am besten, abfangbare schwerwiegende Fehler zu verwenden (wie dies auch der str_replace()
Fall ist, wenn die ersten beiden Argumente geschlossen werden).
preg_replace()
. Darüber hinaus bietet preg_replace()
/ regex die Behandlung von Wortgrenzen (falls gewünscht) - etwas, das Nicht-Regex-Funktionen nicht elegant bieten.
Nach meinem Testergebnis möchte ich den von karim79 bereitgestellten regulären_Ausdruck abstimmen. (Ich habe nicht genug Ruf, um jetzt darüber abzustimmen!)
Die Lösung von zombat verwendet zu viele Funktionsaufrufe, ich vereinfache sogar die Codes. Ich verwende PHP 5.4, um beide Lösungen 100.000 Mal auszuführen, und hier ist das Ergebnis:
$str = 'Hello abc, have a nice day abc! abc!';
$pos = strpos($str, 'abc');
$str = substr_replace($str, '123', $pos, 3);
==> 1,85 Sek
$str = 'Hello abc, have a nice day abc! abc!';
$str = preg_replace('/abc/', '123', $str, 1);
==> 1,35 Sek
Wie du siehst. Die Leistung von preg_replace ist nicht so schlecht, wie viele Leute denken. Daher würde ich die klassische Lösung vorschlagen, wenn Ihr regulärer Express nicht kompliziert ist.
$pos
nach false
. Wenn die Nadel also nicht im Heuhaufen vorhanden ist, wird die Ausgabe beschädigt.
Um die Antwort von zombat (die meiner Meinung nach die beste Antwort ist) zu erweitern, habe ich eine rekursive Version seiner Funktion erstellt, die einen $limit
Parameter enthält, der angibt, wie viele Vorkommen Sie ersetzen möchten.
function str_replace_limit($haystack, $needle, $replace, $limit, $start_pos = 0) {
if ($limit <= 0) {
return $haystack;
} else {
$pos = strpos($haystack,$needle,$start_pos);
if ($pos !== false) {
$newstring = substr_replace($haystack, $replace, $pos, strlen($needle));
return str_replace_limit($newstring, $needle, $replace, $limit-1, $pos+strlen($replace));
} else {
return $haystack;
}
}
}
$start_pos
ist. Wenn die Zeichenfolgenlänge überschritten wird, generiert diese Funktion : Warning: strpos(): Offset not contained in string...
. Diese Funktion kann nicht ersetzt werden, wenn die $start_pos
Länge überschritten wird. Fehlernachweis: 3v4l.org/qGuVIR ... Ihre Funktion kann die return $haystack
Bedingungen kombinieren und vermeiden, Einwegvariablen wie diese zu deklarieren : 3v4l.org/Kdmqp Wie ich jedoch in den Kommentaren an anderer Stelle auf dieser Seite gesagt habe, würde ich es vorziehen Verwenden Sie einen sehr sauberen, direkten, nicht rekursiven preg_replace()
Aufruf.
else
hinzufügen können$start_pos > strlen($haystack) ? $start_pos = strlen($haystack) : '';
Für eine Zeichenfolge
$string = 'OOO.OOO.OOO.S';
$search = 'OOO';
$replace = 'B';
//replace ONLY FIRST occurance of "OOO" with "B"
$string = substr_replace($string,$replace,0,strlen($search));
//$string => B.OOO.OOO.S
//replace ONLY LAST occurance of "OOOO" with "B"
$string = substr_replace($string,$replace,strrpos($string,$search),strlen($search))
//$string => OOO.OOO.B.S
//replace ONLY LAST occurance of "OOOO" with "B"
$string = strrev(implode(strrev($replace),explode(strrev($search),strrev($string),2)))
//$string => OOO.OOO.B.S
Für ein einzelnes Zeichen
$string[strpos($string,$search)] = $replace;
//EXAMPLE
$string = 'O.O.O.O.S';
$search = 'O';
$replace = 'B';
//replace ONLY FIRST occurance of "O" with "B"
$string[strpos($string,$search)] = $replace;
//$string => B.O.O.O.S
//replace ONLY LAST occurance of "O" with "B"
$string[strrpos($string,$search)] = $replace;
// $string => B.O.O.B.S
substr_replace()
Techniken beschädigen die Eingabezeichenfolge, wenn der Suchwert nicht vorhanden ist. Beweis des Scheiterns: 3v4l.org/HmEml (Und diese letzte Technik mit allen rev
Anrufen ist ernsthaft verworren / hart für die Augen.)
Denken Sie daran, dass die gesamte Zeichenfolge ein Array ist:
$string = "Lorem ipsum lá lá lá";
$string[0] = "B";
echo $string;
"Borem ipsum lá lá lá"
á
. Demonstration des Scheiterns
string
es sich um eine Multibyte-Zeichenfolge handelt, indem Siemb_strlen($subject) != strlen($subject)
$str = "/property/details&id=202&test=123#tab-6p";
$position = strpos($str,"&");
echo substr_replace($str,"?",$position,1);
Mit substr_replace können wir das Auftreten des ersten Zeichens nur in einer Zeichenfolge ersetzen. wie & wird mehrmals wiederholt, aber nur an der ersten Position müssen wir & durch ersetzen?
Diese Funktion ist stark von der Antwort von @renocor inspiriert. Es macht die Funktion Multi-Byte-sicher.
function str_replace_limit($search, $replace, $string, $limit)
{
$i = 0;
$searchLength = mb_strlen($search);
while(($pos = mb_strpos($string, $search)) !== false && $i < $limit)
{
$string = mb_substr_replace($string, $replace, $pos, $searchLength);
$i += 1;
}
return $string;
}
function mb_substr_replace($string, $replacement, $start, $length = null, $encoding = null)
{
$string = (array)$string;
$encoding = is_null($encoding) ? mb_internal_encoding() : $encoding;
$length = is_null($length) ? mb_strlen($string) - $start : $length;
$string = array_map(function($str) use ($replacement, $start, $length, $encoding){
$begin = mb_substr($str, 0, $start, $encoding);
$end = mb_substr($str, ($start + $length), mb_strlen($str), $encoding);
return $begin . $replacement . $end;
}, $string);
return ( count($string) === 1 ) ? $string[0] : $string;
}
Sie können dies verwenden:
function str_replace_once($str_pattern, $str_replacement, $string){
if (strpos($string, $str_pattern) !== false){
$occurrence = strpos($string, $str_pattern);
return substr_replace($string, $str_replacement, strpos($string, $str_pattern), strlen($str_pattern));
}
return $string;
}
Fand dieses Beispiel von php.net
Verwendungszweck:
$string = "Thiz iz an examplz";
var_dump(str_replace_once('z','Z', $string));
Ausgabe:
ThiZ iz an examplz
Dies kann die Leistung ein wenig verringern, ist aber die einfachste Lösung.
strpos()
). Heruntergestuft, da der Seite kein neuer Wert hinzugefügt wird.
Wenn Ihre Zeichenfolge keine Multibyte-Zeichen enthält und Sie nur ein Zeichen ersetzen möchten, können Sie sie einfach verwenden strpos
Hier eine Funktion, die Fehler behandelt
/**
* Replace the first occurence of given string
*
* @param string $search a char to search in `$subject`
* @param string $replace a char to replace in `$subject`
* @param string $subject
* @return string
*
* @throws InvalidArgumentException if `$search` or `$replace` are invalid or if `$subject` is a multibytes string
*/
function str_replace_first(string $search , string $replace , string $subject) : string {
// check params
if(strlen($replace) != 1 || strlen($search) != 1) {
throw new InvalidArgumentException('$search & $replace must be char');
}elseif(mb_strlen($subject) != strlen($subject)){
throw new InvalidArgumentException('$subject is an multibytes string');
}
// search
$pos = strpos($subject, $search);
if($pos === false) {
// not found
return $subject;
}
// replace
$subject[$replace] = $subject;
return $subject;
}
Für Schleifenlösung
<?php
echo replaceFirstMatchedChar("&", "?", "/property/details&id=202&test=123#tab-6");
function replaceFirstMatchedChar($searchChar, $replaceChar, $str)
{
for ($i = 0; $i < strlen($str); $i++) {
if ($str[$i] == $searchChar) {
$str[$i] = $replaceChar;
break;
}
}
return $str;
}
Hier ist eine einfache Klasse, die ich erstellt habe, um unsere leicht modifizierten Funktionen str_replace () zu verpacken .
Mit unserer Funktion php :: str_rreplace () können Sie auch einen umgekehrten, begrenzten str_replace () ausführen, was sehr praktisch sein kann, wenn Sie versuchen, nur die letzten X-Instanzen eines Strings zu ersetzen.
Diese Beispiele verwenden beide preg_replace () .
<?php
class php {
/**
* str_replace() from the end of a string that can also be limited e.g. replace only the last instance of '</div>' with ''
*
* @param string $find
* @param string $replace
* @param string $subject
* @param int $replacement_limit | -1 to replace all references
*
* @return string
*/
public static function str_replace($find, $replace, $subject, $replacement_limit = -1) {
$find_pattern = str_replace('/', '\/', $find);
return preg_replace('/' . $find_pattern . '/', $replace, $subject, $replacement_limit);
}
/**
* str_replace() from the end of a string that can also be limited e.g. replace only the last instance of '</div>' with ''
*
* @param string $find
* @param string $replace
* @param string $subject
* @param int $replacement_limit | -1 to replace all references
*
* @return string
*/
public static function str_rreplace($find, $replace, $subject, $replacement_limit = -1) {
return strrev( self::str_replace(strrev($find), strrev($replace), strrev($subject), $replacement_limit) );
}
}
$str = "Hello there folks!"
$str_ex = explode("there, $str, 2); //explodes $string just twice
//outputs: array ("Hello ", " folks")
$str_final = implode("", $str_ex); // glues above array together
// outputs: str("Hello folks")
Es gibt noch einen zusätzlichen Speicherplatz, aber es spielte keine Rolle, da es sich in meinem Fall um ein Backgound-Skript handelte.
Dies ist meine erste Antwort hier, ich hoffe es richtig zu machen. Warum nicht das vierte Argument der Funktion str_replace für dieses Problem verwenden?
mixed str_replace ( mixed $search , mixed $replace , mixed $subject [, int &$count ] )
count: Wenn bestanden, wird dies auf die Anzahl der durchgeführten Ersetzungen gesetzt.
edit: Diese Antwort ist falsch, da der 4. Parameter von str_replace eine Variable ist, der die Anzahl der durchgeführten Ersetzungen zugewiesen wird. Dies ist nicht konsistent mit preg_replace , das einen 4. Parameter $limit
und einen 5. Parameter hat &$count
.
Es ist einfach, eine Lösung zu finden, um nur die ersten oder ersten Instanzen zu ersetzen (indem Sie den Zählwert angeben). Es gibt nicht viele Lösungen, um die letzten oder letzten Instanzen zu ersetzen.
Vielleicht sollte so etwas wie str_replace ($ find, $ replace, $ subject, -3) die letzten drei Instanzen ersetzen.
Jedenfalls nur ein Vorschlag.
s($subject)->replaceFirst($search)
unds($subject)->replaceFirstIgnoreCase($search)
hilfreich, wie in dieser eigenständigen Bibliothek gefunden .