2011-12-14 65 views
8

str_replace用替換替換所有出現的單詞。帶有限制參數的PHP str_replace()?

preg_replace用替換替換模式的出現並採用可選的限制參數。

我不需要任何模式匹配,但想要限制參數的方便性。我應該使用什麼?

+3

字符串仍圖案,雖然簡單圖案。 – Mathletics 2011-12-14 19:10:10

+0

`str_replace`的最後一個參數有什麼問題? – 2015-07-06 07:58:48

回答

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); 
} 

這將允許您對替換次數進行限制。應該使用preg_quote來逃避字符串,以確保任何特殊字符不被解釋爲模式字符。

Demo, BTW


如果你有興趣,here's a version包含&$count說法:

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); 
} 
2
$str = implode($replace, explode($search, $subject, $count + 1)); 

快速的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)); 

輸出(強調):

是,或不是可以在是,這是個問題:
無論這是一件高尚的心靈可以在遭受
吊索和離譜財富的箭頭,
或者挺身反抗人世無邊的苦難,
通過鬥爭他們

請注意,此方法區分大小寫。

1

最初從https://stackoverflow.com/a/11400172/526741

拉着我寫一個函數,用str_replace() 100%的向後兼容。也就是說,你可以替換所有出現str_replace()str_replace_limit()不搞亂任何東西,即使是那些使用數組爲$search$replace,和/或$subject

功能可能是完全獨立的,如果你想與($string===strval(intval(strval($string))))替換函數調用,但我會建議反對,因爲valid_integer()與作爲字符串提供整數打交道時,一個相當實用的功能。

注:只要有可能,str_replace_limit()將使用str_replace()代替,所以str_replace()所有呼叫可以用str_replace_limit()更換,無需擔心一擊性能。

用法
<?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替換 - bbcbbc

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

1替換 - bbcabc

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

2置換 - 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; 

    } 

} 
10

即使世界一個更好的辦法來做到這一點

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