Je veux une version str_replace()
qui ne remplace que la première occurrence de $search
dans le $subject
. Existe-t-il une solution simple à ce problème ou ai-je besoin d'une solution hacky?
Je veux une version str_replace()
qui ne remplace que la première occurrence de $search
dans le $subject
. Existe-t-il une solution simple à ce problème ou ai-je besoin d'une solution hacky?
Réponses:
Peut être fait avec 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 magie est dans le quatrième paramètre optionnel [Limite]. De la documentation:
[Limite] - Le nombre maximal de remplacements possibles pour chaque modèle dans chaque chaîne de sujet. Par défaut à -1 (pas de limite).
Cependant, consultez la réponse de zombat pour une méthode plus efficace (environ 3 à 4 fois plus rapide).
preg_quote
? Par exemple, @ThomasRedstone craint que le délimiteur /
ne soit dangereux s'il apparaît $from
, mais heureusement ce n'est pas le cas: il est correctement échappé à cause du preg_quote
second paramètre de (on peut facilement le tester). Je serais intéressé d'entendre parler de problèmes spécifiques (qui seraient de graves bogues de sécurité PCRE dans mon livre).
Il n'y en a pas de version, mais la solution n'est pas du tout hacky.
$pos = strpos($haystack, $needle);
if ($pos !== false) {
$newstring = substr_replace($haystack, $replace, $pos, strlen($needle));
}
Assez facile et économise la pénalité de performance des expressions régulières.
Bonus: si vous souhaitez remplacer la dernière occurrence, utilisez-la simplement strrpos
à la place de strpos
.
substr_replace
s'agisse d'une fonction quelque peu difficile à utiliser en raison de tous les paramètres, le vrai problème est que la manipulation de chaînes par des nombres est parfois délicate - vous devez faire attention à transmettre la bonne variable / décalage aux fonctions. J'irais même jusqu'à dire que le code ci-dessus est l'approche la plus simple et la plus logique pour moi.
Modifier: les deux réponses ont été mises à jour et sont maintenant correctes. Je vais laisser la réponse car les timings de fonction sont toujours utiles.
Les réponses de «zombat» et «trop de php» ne sont malheureusement pas correctes. Ceci est une révision de la réponse publiée par zombat (car je n'ai pas assez de réputation pour poster un commentaire):
$pos = strpos($haystack,$needle);
if ($pos !== false) {
$newstring = substr_replace($haystack,$replace,$pos,strlen($needle));
}
Notez le strlen ($ needle), au lieu de strlen ($ replace). L'exemple de Zombat ne fonctionnera correctement que si l'aiguille et le remplacement sont de la même longueur.
Voici la même fonctionnalité dans une fonction avec la même signature que str_replace de 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;
}
Ceci est la réponse révisée de «trop de php»:
implode($replace, explode($search, $subject, 2));
Notez le 2 à la fin au lieu de 1. Ou au format de fonction:
function str_replace_first($search, $replace, $subject) {
return implode($replace, explode($search, $subject, 2));
}
J'ai chronométré les deux fonctions et la première est deux fois plus rapide lorsqu'aucune correspondance n'est trouvée. Ils ont la même vitesse lorsqu'un match est trouvé.
stripos()
à la rescousse :-)
Je me suis demandé laquelle était la plus rapide, alors je les ai toutes testées.
Vous trouverez ci-dessous:
Toutes les fonctions ont été testées avec les mêmes paramètres:
$string = 'OOO.OOO.OOO.S';
$search = 'OOO';
$replace = 'B';
Fonctions qui ne remplacent que la première occurrence d'une chaîne dans une chaîne:
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%
Fonctions qui ne remplacent que la dernière occurrence d'une chaîne dans une chaîne:
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()
remporte le résultat est simple; parce que c'est une fonction interne. Deux fonctions internes et définies par l'utilisateur faisant la même chose diffèrent dans les performances, car la fonction interne s'exécute dans les couches inférieures. Alors pourquoi pas preg_match()
? Les expressions régulières sont presque plus lentes que chaque fonction de manipulation de chaîne interne, en raison de leur nation de recherche dans une chaîne plusieurs fois.
substr_replace($string, $replace, 0, strlen($search));
) n'a pas simplement écrit cette statique 0
. Une partie de la convolution des solutions non regex est qu'elles doivent "trouver" le point de départ avant de savoir où remplacer.
Malheureusement, je ne connais aucune fonction PHP qui puisse le faire.
Vous pouvez rouler le vôtre assez facilement comme ceci:
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));
pour les numéros de remplacement personnalisés
J'ai créé cette petite fonction qui remplace chaîne sur chaîne (sensible à la casse) avec limite, sans avoir besoin de Regexp. Ça fonctionne bien.
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;
}
Exemple d'utilisation:
$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
plutôt que d' is_bool(
être plus explicite - je donne ce coup de pouce juste parce qu'il a évité la folie RegExp ! ... et en même temps ça marche et une solution propre ...
preg_
solution facilement personnalisable n'est pas de la folie mais une préférence personnelle. return preg_replace('/'.preg_quote($search, '/').'/', $replace, $content, 1);
est assez simple à lire pour les personnes qui ne craignent pas les regex. Besoin d'une recherche insensible à la casse? Ajoutez i
après le délimiteur de motif de fin. Besoin d'un support unicode / multi-octets? Ajoutez u
après le délimiteur de motif de fin. Besoin de prise en charge des limites de mots? Ajoutez des \b
deux côtés de votre chaîne de recherche. Si vous ne voulez pas d'expression régulière, n'utilisez pas d'expression régulière. Des chevaux pour les cours, mais certainement pas de la folie.
Le moyen le plus simple serait d'utiliser une expression régulière.
L'autre façon est de trouver la position de la chaîne avec strpos () puis un substr_replace ()
Mais j'irais vraiment pour le 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));
}
=> LE CODE A ÉTÉ RÉVISÉ, alors considérez certains commentaires trop anciens
Et merci à tous de m'aider à améliorer cela
Tout BUG, veuillez me communiquer; Je vais arranger ça juste après
Alors, allons-y pour:
Remplacement du premier «o» par «ea» par exemple:
$s='I love you';
$s=str_replace_first('o','ea',$s);
echo $s;
//output: I leave you
La fonction:
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))
, non substr($where,$b+1)
. Et je suppose que substr_replace
c'est plus rapide.
$string = 'this is my world, not my world';
$find = 'world';
$replace = 'farm';
$result = preg_replace("/$find/",$replace,$string,1);
echo $result;
preg_quote
des $find
avant de l' utiliser comme une expression.
preg_quote()
. Cette réponse en double tardive peut être supprimée de la page en toute sécurité car ses conseils sont fournis par la réponse acceptée la plus ancienne et la plus élevée.
Pour développer la réponse de @ renocor , j'ai écrit une fonction qui est 100% rétrocompatible avec str_replace()
. Autrement dit, vous pouvez remplacer toutes les occurrences de str_replace()
avec str_replace_limit()
sans rien gâcher, même ceux qui utilisent des tableaux pour la $search
, $replace
et / ou$subject
.
La fonction pourrait être complètement autonome, si vous vouliez remplacer l'appel de fonction par ($string===strval(intval(strval($string))))
, mais je le déconseille car valid_integer()
c'est une fonction plutôt utile lorsque vous traitez avec des entiers fournis sous forme de chaînes.
Remarque: Dans la mesure du possible, str_replace_limit()
utilisera à la str_replace()
place, de sorte que tous les appels à str_replace()
puissent être remplacés str_replace_limit()
sans se soucier de la 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 remplacements - bbcbbc
$limit = 1; // Limit of 1
$new_string = str_replace_limit($search, $replace, $subject, $count, $limit);
echo $count.' replacements -- '.$new_string;
1 remplacements - bbcabc
$limit = 10; // Limit of 10
$new_string = str_replace_limit($search, $replace, $subject, $count, $limit);
echo $count.' replacements -- '.$new_string;
2 remplacements - 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
partout, ce qui est un avertissement et non une erreur . La trace est extrêmement utile pour savoir quel code transmet les données non valides à la fonction en premier lieu (ce qui est absolument nécessaire pour traquer les bogues en production). Quant au retour $subject
au lieu de false
/ null
ou le lancement d'une erreur, c'était simplement un choix personnel pour mon cas d'utilisation. Pour faire correspondre str_replace()
la fonctionnalité de, l'utilisation d'erreurs fatales capturables serait le meilleur pari (tout comme str_replace()
lors de la fermeture des deux premiers arguments).
preg_replace()
. De plus, preg_replace()
/ regex offre une gestion des limites des mots (si cela est souhaitable) - quelque chose que les fonctions non regex ne fourniront pas avec élégance.
Selon mon résultat de test, je voudrais voter celui regular_express fourni par karim79. (Je n'ai pas assez de réputation pour le voter maintenant!)
La solution de zombat utilise trop d'appels de fonctions, je simplifie même les codes. J'utilise PHP 5.4 pour exécuter les deux solutions 100 000 fois, et voici le résultat:
$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
Comme vous pouvez le voir. La performance de preg_replace n'est pas aussi mauvaise que beaucoup de gens le pensent. Je suggère donc la solution chic si votre express régulier n'est pas compliqué.
$pos
pour false
, donc quand l'aiguille n'existe pas dans la botte de foin, il endommagera la sortie.
Pour développer la réponse de zombat (que je pense être la meilleure réponse), j'ai créé une version récursive de sa fonction qui prend un $limit
paramètre pour spécifier le nombre d'occurrences que vous souhaitez remplacer.
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
, donc si elle est au - delà de la longueur de chaîne, cette fonction génère: Warning: strpos(): Offset not contained in string...
. Cette fonction ne parvient pas à effectuer un remplacement lorsqu'elle $start_pos
est au-delà de la longueur. Preuve d'échec: 3v4l.org/qGuVIR ... Votre fonction peut combiner les return $haystack
conditions et éviter de déclarer des variables à usage unique comme ceci: 3v4l.org/Kdmqp Cependant, comme je l'ai dit dans les commentaires ailleurs sur cette page, je préfère utiliser un appel très net, direct et non récursif preg_replace()
.
else
déclaration de ligne$start_pos > strlen($haystack) ? $start_pos = strlen($haystack) : '';
Pour une chaîne
$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
Pour un seul personnage
$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()
techniques endommagent la chaîne d'entrée lorsque la valeur de recherche n'est pas présente. Preuve d'échec: 3v4l.org/HmEml (Et cette dernière technique avec tous les rev
appels est sérieusement alambiquée / dure pour les yeux.)
En complément de ce que les gens ont dit, rappelez-vous que la chaîne entière est un tableau:
$string = "Lorem ipsum lá lá lá";
$string[0] = "B";
echo $string;
"Borem ipsum lá lá lá"
á
. Démonstration d'échec
string
chaîne est multi-octets en utilisantmb_strlen($subject) != strlen($subject)
$str = "/property/details&id=202&test=123#tab-6p";
$position = strpos($str,"&");
echo substr_replace($str,"?",$position,1);
En utilisant substr_replace, nous pouvons remplacer l'occurrence du premier caractère uniquement dans la chaîne. comme & est répété plusieurs fois mais seulement en première position nous devons remplacer & avec?
Cette fonction est fortement inspirée de la réponse de @renocor. Il rend la fonction multi-octets sûre.
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;
}
Vous pouvez utiliser ceci:
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;
}
Trouvé cet exemple sur php.net
Usage:
$string = "Thiz iz an examplz";
var_dump(str_replace_once('z','Z', $string));
Production:
ThiZ iz an examplz
Cela peut réduire un peu les performances, mais c'est la solution la plus simple.
strpos()
). Voté parce qu'il n'ajoute aucune nouvelle valeur à la page.
Si votre chaîne ne contient aucun caractère multi-octets et si vous souhaitez remplacer un seul caractère, vous pouvez simplement utiliser strpos
Voici une fonction qui gère les erreurs
/**
* 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;
}
Pour la solution de boucle
<?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;
}
Voici une classe simple que j'ai créée pour encapsuler nos fonctions str_replace () légèrement modifiées .
Notre fonction php :: str_rreplace () vous permet également d'effectuer une opération inverse, limitée str_replace () qui peut être très pratique lorsque vous essayez de remplacer uniquement les instances X finales d'une chaîne.
Ces exemples utilisent tous deux 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")
Il y a un espace supplémentaire, mais cela n'avait pas d'importance comme c'était le cas pour le script d'arrière-plan dans mon cas.
c'est ma première réponse ici, j'espère le faire correctement. Pourquoi ne pas utiliser le quatrième argument de la fonction str_replace pour ce problème?
mixed str_replace ( mixed $search , mixed $replace , mixed $subject [, int &$count ] )
count: S'il est réussi, il sera défini sur le nombre de remplacements effectués.
edit: Cette réponse est fausse, car le 4ème paramètre de str_replace est une variable qui obtient le nombre de remplacements effectués. Ceci n'est pas cohérent avec preg_replace , qui a un 4ème paramètre $limit
et un 5ème paramètre &$count
.
Il est facile de trouver une solution pour remplacer uniquement le premier ou le premier couple d'instances (en donnant la valeur de comptage). Il n'y a pas beaucoup de solutions pour remplacer le dernier ou le dernier couple d'instances.
Peut-être que quelque chose comme str_replace ($ find, $ replace, $ subject, -3) devrait remplacer les trois dernières instances.
Quoi qu'il en soit, juste une suggestion.
s($subject)->replaceFirst($search)
ets($subject)->replaceFirstIgnoreCase($search)
utile, comme dans cette bibliothèque autonome .