带有限制参数的PHP str_replace()?

时间:2011-12-14 19:07:24

标签: php

str_replace用替换替换所有出现的单词。

preg_replace用替换替换模式的出现,并采用可选的限制参数。

我不需要模式匹配,但想要限制参数的便利性。我该怎么用?

5 个答案:

答案 0 :(得分:9)

这是一个更好的方法

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

答案 1 :(得分:3)

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 :(得分: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));

输出(强调添加):

  

是否 CAN IT ,这就是问题:
  是否在心中的Nobler CAN IT 受到影响   离谱的财富的纵向和箭头,
  或者采取武器对抗麻烦的海洋,
  并反对结束他们

请注意,此方法区分大小写。

答案 3 :(得分:1)

最初来自https://stackoverflow.com/a/11400172/526741

我编写了一个与str_replace() 100%向后兼容的函数。也就是说,您可以将str_replace()的{​​strong>所有次出现替换为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;

    }

}

答案 4 :(得分:0)

这是@ brad-christie的答案的增强版本,它将数组广告兼容为$ find和$ replace值:

function str_replace_limit($find, $replacement, $subject, $limit = 0) {

    if ($limit == 0)
      return str_replace($find, $replacement, $subject);

    for ($i = 0; $i < count($find); $i++) {
      $find[$i] = '/' . preg_quote($find[$i],'/') . '/';
    }

    return preg_replace($find, $replacement, $subject, $limit);
  }