Voglio una versione str_replace()
che sostituisce solo la prima occorrenza di $search
in $subject
. C'è una soluzione semplice a questo, o ho bisogno di una soluzione hacky?
Voglio una versione str_replace()
che sostituisce solo la prima occorrenza di $search
in $subject
. C'è una soluzione semplice a questo, o ho bisogno di una soluzione hacky?
Risposte:
Può essere fatto con preg_replace :
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'
La magia è nel quarto parametro opzionale [Limite]. Dalla documentazione:
[Limite] - Il numero massimo possibile di sostituzioni per ciascun motivo in ciascuna stringa di soggetto. Il valore predefinito è -1 (nessun limite).
Tuttavia , vedi la risposta di zombat per un metodo più efficiente (circa 3-4 volte più veloce).
preg_quote
? Ad esempio, @ThomasRedstone teme che il delimitatore /
potrebbe essere pericoloso se appare $from
, ma per fortuna non lo è: è correttamente evaso a causa del preg_quote
secondo parametro (si può facilmente testarlo). Sarei interessato a conoscere questioni specifiche (che sarebbero gravi bug di sicurezza di PCRE nel mio libro).
Non ne esiste una versione, ma la soluzione non è affatto confusa.
$pos = strpos($haystack, $needle);
if ($pos !== false) {
$newstring = substr_replace($haystack, $replace, $pos, strlen($needle));
}
Abbastanza facile e salva la penalità prestazionale delle espressioni regolari.
Bonus: se si desidera sostituire l' ultima occorrenza, basta usare strrpos
al posto di strpos
.
substr_replace
sia una funzione un po 'ingombrante da utilizzare a causa di tutti i parametri, il vero problema è che fare manipolazione di stringhe con i numeri è talvolta complicato : devi stare attento a passare la variabile / offset giusta alle funzioni. In realtà andrei fino al punto di dire che il codice sopra è l'approccio più diretto e per me logico.
Modifica: entrambe le risposte sono state aggiornate e ora sono corrette. Lascerò la risposta poiché i tempi delle funzioni sono ancora utili.
Purtroppo le risposte di "zombat" e "too php" non sono corrette. Questa è una revisione della risposta postata da zombat (dato che non ho abbastanza reputazione per pubblicare un commento):
$pos = strpos($haystack,$needle);
if ($pos !== false) {
$newstring = substr_replace($haystack,$replace,$pos,strlen($needle));
}
Nota lo strlen ($ ago), anziché lo strlen ($ rimpiazza). L'esempio di Zombat funzionerà correttamente solo se ago e sostituzione hanno la stessa lunghezza.
Ecco la stessa funzionalità in una funzione con la stessa firma dello str_replace di PHP:
function str_replace_first($search, $replace, $subject) {
$pos = strpos($subject, $search);
if ($pos !== false) {
return substr_replace($subject, $replace, $pos, strlen($search));
}
return $subject;
}
Questa è la risposta rivista di "troppo php":
implode($replace, explode($search, $subject, 2));
Nota il 2 alla fine invece di 1. O nel formato della funzione:
function str_replace_first($search, $replace, $subject) {
return implode($replace, explode($search, $subject, 2));
}
Ho cronometrato le due funzioni e la prima è due volte più veloce quando non viene trovata alcuna corrispondenza. Hanno la stessa velocità quando viene trovata una corrispondenza.
stripos()
in soccorso :-)
Mi chiedevo quale fosse il più veloce, quindi li ho testati tutti.
Di seguito troverai:
Tutte le funzioni sono state testate con le stesse impostazioni:
$string = 'OOO.OOO.OOO.S';
$search = 'OOO';
$replace = 'B';
Funzioni che sostituiscono solo la prima occorrenza di una stringa all'interno di una stringa:
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%
Funzioni che sostituiscono solo l'ultima occorrenza di una stringa all'interno di una stringa:
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()
vince il risultato è semplice; perché è una funzione interna. Due funzioni interne e definite dall'utente che fanno la stessa cosa differiscono nelle prestazioni, perché quella interna viene eseguita in livelli inferiori. Quindi, perché no preg_match()
? Le espressioni regolari sono quasi più lente di ogni funzione di manipolazione di stringhe interna, a causa della loro nazione di ricerca in una stringa più volte.
substr_replace($string, $replace, 0, strlen($search));
) non abbia semplicemente scritto quella statica 0
. Parte della convoluzione delle soluzioni non regex è che devono "trovare" il punto di partenza prima di sapere dove sostituire.
Sfortunatamente, non conosco alcuna funzione PHP in grado di farlo.
Puoi arrotolarlo abbastanza facilmente in questo modo:
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));
per i numeri di sostituzione personalizzati
Ho creato questa piccola funzione che sostituisce stringa su stringa (con distinzione tra maiuscole e minuscole) con limite, senza la necessità di Regexp. Funziona bene
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;
}
Esempio di utilizzo:
$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
invece di is_bool(
essere più esplicito - sto dando questo pollice in su solo perché ha evitato la follia di RegExp ! ... e allo stesso tempo funziona e una soluzione pulita ...
preg_
soluzione facilmente personalizzabile non è follia ma una preferenza personale. return preg_replace('/'.preg_quote($search, '/').'/', $replace, $content, 1);
è piuttosto semplice da leggere per le persone che non temono la regex. Hai bisogno di una ricerca senza distinzione tra maiuscole e minuscole? Aggiungi i
dopo il delimitatore del modello finale. Hai bisogno del supporto Unicode / Multibyte? Aggiungi u
dopo il delimitatore del modello finale. Hai bisogno di supporto per i confini di parole? Aggiungi \b
su entrambi i lati della stringa di ricerca. Se non vuoi regex, non usare regex. Cavalli per i corsi, ma certamente non follia.
Il modo più semplice sarebbe usare l'espressione regolare.
L'altro modo è trovare la posizione della stringa con strpos () e quindi un substr_replace ()
Ma andrei davvero per il RegExp.
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));
}
=> IL CODICE È STATO RIVEDUTO, quindi considera alcuni commenti troppo vecchi
E grazie a tutti per avermi aiutato a migliorarlo
Qualsiasi BUG, per favore comunicami; Lo aggiusterò subito dopo
Quindi, andiamo per:
Sostituendo la prima 'o' in 'ea' per esempio:
$s='I love you';
$s=str_replace_first('o','ea',$s);
echo $s;
//output: I leave you
La funzione:
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))
, no substr($where,$b+1)
. E immagino che substr_replace
sia più veloce.
$string = 'this is my world, not my world';
$find = 'world';
$replace = 'farm';
$result = preg_replace("/$find/",$replace,$string,1);
echo $result;
preg_quote
di $find
prima di utilizzarlo come espressione.
preg_quote()
. Questa risposta duplicata in ritardo può essere eliminata in modo sicuro dalla pagina perché i suoi consigli sono forniti dalla precedente e una risposta accettata con voto più elevato.
Per espandere la risposta di @ renocor , ho scritto una funzione compatibile al 100% con le versioni precedenti str_replace()
. Cioè, è possibile sostituire tutte le occorrenze di str_replace()
con str_replace_limit()
senza rovinare nulla fino, anche quelle che utilizzano le matrici per la $search
, $replace
e / o $subject
.
La funzione potrebbe essere completamente autonoma, se si desidera sostituire la chiamata di funzione con ($string===strval(intval(strval($string))))
, ma lo sconsiglio poiché valid_integer()
è una funzione piuttosto utile quando si tratta di numeri interi forniti come stringhe.
Nota: quando possibile, str_replace_limit()
utilizzerà str_replace()
invece, in modo che tutte le chiamate a str_replace()
possano essere sostituite str_replace_limit()
senza preoccuparsi di un colpo alla performance.
<?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 sostituzioni - bbcbbc
$limit = 1; // Limit of 1
$new_string = str_replace_limit($search, $replace, $subject, $count, $limit);
echo $count.' replacements -- '.$new_string;
1 rimpiazzi - bbcabc
$limit = 10; // Limit of 10
$new_string = str_replace_limit($search, $replace, $subject, $count, $limit);
echo $count.' replacements -- '.$new_string;
2 sostituzioni - 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
dappertutto, che è un avvertimento , non un errore . Il backtrace è estremamente utile per scoprire quale codice sta trasmettendo i dati non validi alla funzione in primo luogo (che è assolutamente necessario per rintracciare i bug in produzione). Per quanto riguarda la restituzione $subject
anziché false
/ null
o il lancio di un errore, è stata semplicemente una scelta personale per il mio caso d'uso. Per abbinare str_replace()
la funzionalità, usare errori fatali catchable sarebbe la scommessa migliore (come str_replace()
quando si fornisce una chiusura per i primi due argomenti).
preg_replace()
. Inoltre, preg_replace()
/ regex offre la gestione dei limiti di parola (se desiderabile) - qualcosa che le funzioni non regex non forniranno in modo elegante.
Secondo il mio risultato del test, vorrei votare quello regular_express fornito da karim79. (Non ho abbastanza reputazione per votarla adesso!)
La soluzione di zombat utilizza troppe chiamate di funzioni, ho anche semplificato i codici. Sto usando PHP 5.4 per eseguire entrambe le soluzioni per 100.000 volte, ed ecco il risultato:
$str = 'Hello abc, have a nice day abc! abc!';
$pos = strpos($str, 'abc');
$str = substr_replace($str, '123', $pos, 3);
==> 1,85 sec
$str = 'Hello abc, have a nice day abc! abc!';
$str = preg_replace('/abc/', '123', $str, 1);
==> 1,35 sec
Come potete vedere. Le prestazioni di preg_replace non sono così male come pensano molte persone. Quindi suggerirei la soluzione di classe se il tuo espresso regolare non è complicato.
$pos
per false
, in modo che quando l'ago non esiste nel pagliaio, danneggerà l'uscita.
Per espandere la risposta di zombat (che credo sia la migliore risposta), ho creato una versione ricorsiva della sua funzione che accetta un $limit
parametro per specificare quante occorrenze si desidera sostituire.
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
, quindi se è oltre la lunghezza della stringa, questa funzione genera: Warning: strpos(): Offset not contained in string...
. Questa funzione non riesce a effettuare una sostituzione quando $start_pos
è oltre la lunghezza. Prova di fallimento: 3v4l.org/qGuVIR ... La tua funzione può combinare le return $haystack
condizioni ed evitare di dichiarare variabili monouso come questa: 3v4l.org/Kdmqp Tuttavia, come ho detto nei commenti altrove in questa pagina, preferirei usa una preg_replace()
chiamata molto pulita, diretta, non ricorsiva .
else
linement$start_pos > strlen($haystack) ? $start_pos = strlen($haystack) : '';
Per una stringa
$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
Per un singolo personaggio
$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()
tecniche danneggiano la stringa di input quando il valore di ricerca non è presente. Prova di fallimento: 3v4l.org/HmEml (E quell'ultima tecnica con tutte le rev
chiamate è seriamente contorta / dura per gli occhi.)
A complemento di ciò che la gente ha detto, ricorda che l'intera stringa è un array:
$string = "Lorem ipsum lá lá lá";
$string[0] = "B";
echo $string;
"Borem ipsum lá lá lá"
á
. Dimostrazione di fallimento
string
è una stringa multibyte usandomb_strlen($subject) != strlen($subject)
$str = "/property/details&id=202&test=123#tab-6p";
$position = strpos($str,"&");
echo substr_replace($str,"?",$position,1);
Usando substr_replace possiamo sostituire la ricorrenza del primo carattere solo nella stringa. come è ripetuto più volte ma solo alla prima posizione dobbiamo sostituire e con?
Questa funzione è fortemente ispirata dalla risposta di @renocor. Rende sicura la funzione multi byte.
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;
}
Puoi usare questo:
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;
}
Trovato questo esempio da php.net
Uso:
$string = "Thiz iz an examplz";
var_dump(str_replace_once('z','Z', $string));
Produzione:
ThiZ iz an examplz
Ciò può ridurre leggermente le prestazioni, ma la soluzione più semplice.
strpos()
). Sottovalutato perché non aggiunge alcun nuovo valore alla pagina.
Se la stringa non contiene caratteri multibyte e se si desidera sostituire solo un carattere, è possibile utilizzare semplicemente strpos
Qui una funzione che gestisce gli errori
/**
* 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;
}
Per la soluzione Loop
<?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;
}
Ecco una semplice classe che ho creato per racchiudere le nostre funzioni str_replace () leggermente modificate .
La nostra funzione php :: str_rreplace () consente anche di eseguire str_replace () inverso e limitato, che può essere molto utile quando si tenta di sostituire solo le istanze X finali di una stringa.
Questi esempi usano entrambi 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")
C'è un ulteriore spazio aggiuntivo, ma nel mio caso non importava come lo script backgound.
questa è la mia prima risposta qui, spero di farlo correttamente. Perché non utilizzare il quarto argomento della funzione str_replace per questo problema?
mixed str_replace ( mixed $search , mixed $replace , mixed $subject [, int &$count ] )
conteggio: se superato, verrà impostato sul numero di sostituzioni eseguite.
modifica: questa risposta è errata, poiché il quarto parametro di str_replace è una variabile a cui viene assegnato il numero di sostituzioni eseguite. Ciò non è coerente con preg_replace , che ha un quarto parametro $limit
e un quinto parametro &$count
.
È facile trovare una soluzione per sostituire solo la prima o la prima coppia di istanze (fornendo il valore di conteggio). Non ci sono molte soluzioni per sostituire l'ultima o l'ultima coppia di istanze.
Forse qualcosa come str_replace ($ find, $ replace, $ subject, -3) dovrebbe sostituire le ultime tre istanze.
Comunque, solo un suggerimento.
s($subject)->replaceFirst($search)
es($subject)->replaceFirstIgnoreCase($search)
utile, come si trova in questa libreria indipendente .