2011-12-14 32 views
8

str_replace reemplaza todas las apariciones de una palabra con un reemplazo.PHP str_replace() con un parámetro de límite?

preg_replace reemplaza las apariciones de un patrón con un reemplazo y toma un parámetro de límite opcional.

No tengo ninguna necesidad de coincidencia de patrones, pero me gustaría la conveniencia de un parámetro de límite. ¿Qué debería estar usando?

+3

cadenas siguen siendo los patrones, aunque sencilla patrones. – Mathletics

+0

¿Qué pasa con el último argumento de 'str_replace'? –

+0

@Sebastien C. Ese argumento es obtener el número de reemplazos realizados. Pero no limita la cantidad de reemplazos realizados. – DocRattie

Respuesta

2
function str_replace2($find, $replacement, $subject, $limit = 0){ 
    if ($limit == 0) 
    return str_replace($find, $replacement, $subject); 
    $ptn = '/' . preg_quote($find,'/') . '/'; 
    return preg_replace($ptn, $replacement, $subject, $limit); 
} 

Eso le permitirá establecer un límite en el número de reemplazos. Las cadenas se deben escapar usando preg_quote para asegurarse de que ningún carácter especial sea interpretado como un carácter de patrón.

Demo, BTW


En caso de que esté interesado, here's a version que incluye el &$count argumento:

function str_replace2($find, $replacement, $subject, $limit = 0, &$count = 0){ 
    if ($limit == 0) 
    return str_replace($find, $replacement, $subject, $count); 
    $ptn = '/' . preg_quote($find,'/') . '/'; 
    return preg_replace($ptn, $replacement, $subject, $limit, $count); 
} 
+0

Lo tomaré como correcto ya que funciona para hacer lo que estoy buscando. Esta es casi exactamente la solución en la que me había acostumbrado, pero quería evitar la sobrecarga previa si fuera posible, ya que no necesito una coincidencia de expresiones regulares/patrones. – buley

+0

@editor: Bueno, puedes escribir uno que 'strpos' y' substr's para las coincidencias, pero sería un poco más de trabajo (y podría decirse que es más rápido/flor porque estás haciendo el procesamiento fuera del motor). Depende de usted, aunque sería interesante ver una comparación de referencia. –

+0

'$ count' debe venir antes de' $ limit', para ser compatible con 'str_replace()'. Además, su código solo admite cadenas, mientras que 'str_replace()' admite matrices para '$ search',' $ replace' y '$ subject'. – 0b10011

2
$str = implode($replace, explode($search, $subject, $count + 1)); 

rápida PoC:

$str = 
"To be, or not to be, that is the question: 
Whether 'tis Nobler in the mind to suffer 
The Slings and Arrows of outrageous Fortune, 
Or to take Arms against a Sea of troubles, 
And by opposing end them"; 

/* Replace the first 2 occurrences of 'to' with 'CAN IT' in $str. */ 
echo implode('CAN IT', explode('to', $str, 3)); 

salida (énfasis añadido):

Para ser, o no ¿Puede ser, esa es la cuestión:
Si es más noble en la mente PUEDE sufrir
las hondas y las flechas de la fortuna indignante,
O a tomar las armas contra un mar de problemas,
Y por oponerse a ellos terminan

Tenga en cuenta que este método distingue entre mayúsculas y minúsculas.

1

sacó Originalmente desde https://stackoverflow.com/a/11400172/526741

He escrito una función que es compatible con versiones anteriores del 100% con str_replace(). Es decir, se puede reemplazar todas las ocurrencias destr_replace() con str_replace_limit() sin jugar a nada, incluso aquellos que utilizan matrices para el $search, $replace, y/o $subject.

La función podría ser completamente autónomo, si desea reemplazar la llamada a función con ($string===strval(intval(strval($string)))), pero me gustaría recomendar en contra de ella desde valid_integer() es una función bastante útil cuando se trata de números enteros proporcionados como cadenas.

Nota: Siempre que sea posible, str_replace_limit() utilizará str_replace() lugar, por lo que todas las llamadas a str_replace() pueden ser reemplazados por str_replace_limit() sin preocuparse por un golpe en el rendimiento.

de uso

<?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 reemplazos - bbcbbc

$limit = 1; // Limit of 1 
$new_string = str_replace_limit($search, $replace, $subject, $count, $limit); 
echo $count.' replacements -- '.$new_string; 

1 reemplazos - bbcabc

$limit = 10; // Limit of 10 
$new_string = str_replace_limit($search, $replace, $subject, $count, $limit); 
echo $count.' replacements -- '.$new_string; 

2 reemplazos - bbcbbc

Función

<?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; 

    } 

} 
10

Hay una mejor manera de hacer esto

<? 
$str = 'abcdef abcdef abcdef'; 
// pattern, replacement, string, limit 
echo preg_replace('/abc/', '123', $str, 1); // outputs '123def abcdef abcdef' 
?>