Используя str_replace, чтобы он действовал только в первом матче?

235

Мне нужна версия str_replace(), которая заменяет первое вхождение $search в $subject. Есть ли простое решение для этого, или мне нужно хакерское решение?

Теги:
string

22 ответа

241
Лучший ответ

Может быть сделано с preg_replace:

function str_replace_first($from, $to, $subject)
{
    $from = '/'.preg_quote($from, '/').'/';

    return preg_replace($from, $to, $subject, 1);
}

echo str_replace_first('abc', '123', 'abcdef abcdef abcdef'); 
// outputs '123def abcdef abcdef'

Магия находится в необязательном четвертом параметре [Предел]. Из документации:

[Предел] - Максимально возможный замены для каждого шаблона в каждом предметная строка. По умолчанию -1 (нет предел).


Хотя, см. zombat answer для более эффективного метода (примерно 3-4 раза быстрее).

  • 38
    Недостатком этого метода является снижение производительности регулярных выражений.
  • 27
    Другим недостатком является то, что вы должны использовать preg_quote () на «игле» и избегать метасимволов $ и \ при замене.
Показать ещё 11 комментариев
390

Нет версии, но решение вообще не хаки.

$pos = strpos($haystack, $needle);
if ($pos !== false) {
    $newstring = substr_replace($haystack, $replace, $pos, strlen($needle));
}

Довольно легко и сохраняет штраф за выполнение регулярных выражений.


Бонус: если вы хотите заменить последнее вхождение, просто используйте strrpos вместо strpos.

  • 14
    Может быть намного быстрее и использовать меньше памяти, чем регулярные выражения. Не знаю, почему кто-то проголосовал бы за это ...
  • 12
    Мне нравится такой подход, но в коде есть ошибка, последний параметр вызова substr_replace должен быть strlen ($ needle) вместо strlen ($ replace) .. пожалуйста, будьте осторожны!
Показать ещё 9 комментариев
82

Изменить: оба ответа были обновлены и теперь верны. Я оставлю ответ, поскольку временные параметры функции по-прежнему полезны.

Ответы "zombat" и "too much php", к сожалению, неверны. Это пересмотр ответа zombat (как у меня недостаточно репутации для публикации комментария):

$pos = strpos($haystack,$needle);
if ($pos !== false) {
    $newstring = substr_replace($haystack,$replace,$pos,strlen($needle));
}

Обратите внимание на strlen ($ needle) вместо strlen ($ replace). Пример Zombat будет работать только правильно, если игла и замена имеют одинаковую длину.

Здесь та же функциональность в функции с той же сигнатурой, что и PHP, str_replace:

function str_replace_first($search, $replace, $subject) {
    $pos = strpos($subject, $search);
    if ($pos !== false) {
        return substr_replace($subject, $replace, $pos, strlen($search));
    }
    return $subject;
}

Это пересмотренный ответ "too much php":

implode($replace, explode($search, $subject, 2));

Обратите внимание на 2 в конце вместо 1. Или в формате функции:

function str_replace_first($search, $replace, $subject) {
    return implode($replace, explode($search, $subject, 2));
}

Я приурочил две функции, а первая - в два раза быстрее, когда совпадение не найдено. Они имеют одинаковую скорость, когда совпадение найдено.

  • 0
    Почему бы не обобщить это так: str_replace_furable (mixed $ s, mixed $ r, int $ offset, int $ limit), где функция заменяет вхождения $ limit, начиная с соответствия $ offset (nth).
  • 0
    Жаль, что это применимо только для замены с учетом регистра.
Показать ещё 1 комментарий
58

Я задавался вопросом, какой из них был самым быстрым, поэтому я тестировал их все.

Ниже вы найдете:

  • Полный список всех функций, которые были внесены на эту страницу
  • Тестирование производительности для каждой задачи (среднее время выполнения более 10 000 циклов)
  • Ссылки на каждый ответ (для полного кода)

Все функции были протестированы с теми же настройками:

$string = 'OOO.OOO.OOO.S';
$search = 'OOO'; 
$replace = 'B';

Функции, которые заменяют первое появление строки внутри строки:


Функции, которые заменяют последнее на строку в строке:

  • 0
    Спасибо за это, я обычно использую preg_replace, так как он наиболее гибок, если в большинстве случаев потребуется будущая настройка, но на 27% медленнее не будет значительным
  • 0
    @oLinkWebDevelopment Мне было бы интересно увидеть ваш тестовый скрипт. Я думаю, что это может оказаться полезным.
Показать ещё 2 комментария
47

К сожалению, я не знаю никакой функции PHP, которая может это сделать.
Вы можете довольно легко прокручивать свои слова следующим образом:

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));
}
  • 0
    Я думаю, что это самая лучшая версия из всех - использование join вместо implode .
5

Я создал эту небольшую функцию, которая заменяет строку на строку (с учетом регистра) с лимитом, без необходимости в Regexp. Он отлично работает.

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

Пример использования:

$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
  • 0
    Хотя я предпочел бы сделать ===false вместо is_bool( чтобы быть более is_bool( - я отказываюсь от этого большого пальца только потому, что он избежал безумия RegExp ! ... и в то же время это рабочее и чистое решение .. ,
  • 0
    Предпочитать легко настраиваемое решение preg_ - это не безумие, а личное предпочтение. return preg_replace('/'.preg_quote($search, '/').'/', $replace, $content, 1); довольно просто читать для людей, которые не боятся регулярных выражений. Нужен поиск без учета регистра? Добавьте i после конечного разделителя. Нужна поддержка Unicode / Multibyte? Добавьте u после конечного разделителя. Нужна поддержка границ слов? Добавьте \b с обеих сторон вашей строки поиска. Если вы не хотите использовать регулярные выражения, не используйте регулярные выражения. Лошади на курсах, но уж точно не безумие.
3

Замена первого 'o' на 'ea', например:

$a='I love you';
echo str_replace_first('o','ea',$a);

//output: I leave you

Функция:

function str_replace_first($this,$that,$where)
{
        $b=strpos($where,$this);
        return substr($where,0,$b).$that.substr($where,$b+1);
}
  • 0
    Сбой, если $ это повторяет символы, такие как aaa vs aaaaaaaaa
  • 0
    Я думаю, что это должно быть substr($where,$b+strlen($this)) , а не substr($where,$b+1) . И я думаю, что substr_replace быстрее.
Показать ещё 7 комментариев
3
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));
}
  • 0
    Ответы только на код не имеют большого значения в StackOverflow, потому что они плохо справляются с обучением / расширением возможностей тысяч будущих исследователей.
3
$string = 'this is my world, not my world';
$find = 'world';
$replace = 'farm';
$result = preg_replace("/$find/",$replace,$string,1);
echo $result;
  • 0
    Это так же, как первый ответ. Кроме того, вы должны сделать preg_quote из $find прежде чем использовать его в качестве выражения.
  • 0
    это то, что я использовал, поэтому я проголосовал за это. Первый ответ вызвал конфликт с Drupal, он должен был перезаписать вспомогательную функцию drupal. Итак, я просто взял код, который был внутри функции, и использовал его в соответствии с остальным кодом ...
Показать ещё 1 комментарий
3

Самый простой способ - использовать регулярное выражение.

Другой способ - найти позицию строки с strpos(), а затем substr_replace()

Но я бы действительно пошел на RegExp.

  • 0
    Этот «намек» довольно расплывчатый / низкозначный по сравнению с другими постами на этой странице.
2

В дополнение к тому, что говорили люди, помните, что вся строка является массивом:

$string = "Lorem ipsum lá lá lá";

$string[0] = "B";

echo $string;

"Borem ipsum lá lá lá"

  • 2
    Если он не содержит многобайтовые символы ... и тогда ваша техника не сработает. Как жаль, что вы предложили образец входной строки, содержащей á . Демонстрация неудачи
  • 0
    Вы можете проверить, является ли ваша string многобайтовой строкой, используя mb_strlen($subject) != strlen($subject)
Показать ещё 1 комментарий
2

Для строки

$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

Для одного символа

$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
  • 0
    Первый фрагмент substr_replace () завершается ошибкой, когда строка поиска не находится со смещением 0 входной строки. Подтверждение ошибки: 3v4l.org/oIbRv И оба метода substr_replace() повреждают входную строку, когда значение поиска отсутствует. Доказательство неудачи: 3v4l.org/HmEml (И эта последняя техника со всеми вызовами rev серьезно запутана / трудна для глаз.)
2

Чтобы расширить ответ на зомбат (который я считаю лучшим ответом), я создал рекурсивную версию его функции, которая принимает параметр $limit, чтобы указать, сколько вхождений вы хотите заменить.

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;
        }
    }
}
  • 0
    Обратите внимание, что проверка $start_pos , поэтому, если она превышает длину строки, эта функция сгенерирует: Warning: strpos(): Offset not contained in string... Эта функция не может выполнить замену, когда $start_pos превышает длину. Proof of Failure: 3v4l.org/qGuVIR ... Ваша функция может объединять условия return $haystack и избегать объявления одноразовых переменных, таких как: 3v4l.org/Kdmqp Однако, как я уже говорил в комментариях в других местах на этой странице, Я бы предпочел использовать очень чистый прямой нерекурсивный preg_replace() .
2

В соответствии с моим результатом теста, я хочу проголосовать за обычный_express, предоставленный karim79. (У меня нет достаточной репутации, чтобы проголосовать сейчас!)

Решение от zombat использует слишком много вызовов функций, я даже упрощаю коды. Я использую PHP 5.4 для запуска обоих решений в 100 000 раз, и вот результат:

$str = 'Hello abc, have a nice day abc! abc!';
$pos = strpos($str, 'abc');
$str = substr_replace($str, '123', $pos, 3);

== > 1,85 с

$str = 'Hello abc, have a nice day abc! abc!';
$str = preg_replace('/abc/', '123', $str, 1);

== > 1,35 с

Как вы можете видеть. Производительность preg_replace не так уж плоха, как думают многие. Поэтому я предлагаю классное решение, если ваш обычный экспресс не является сложным.

  • 0
    Ваш первый фрагмент - несправедливое сравнение, потому что он не использует правильную реализацию. Вы не проверяете $pos на false , поэтому, если иголка не существует в стоге сена, это повредит вывод.
  • 0
    Спасибо @mickmackusa, ты прав. Но дело не в этом. Я сказал, что этот код упрощен только для сравнения эффективности реализаций.
Показать ещё 2 комментария
2

В PHP вы можете перебирать буквы строки или обращаться к буквам, так как можно получить доступ к элементам массива.

Фрагмент, который воспроизводит только первую букву строки:

$word[0] = str_replace($find, $replace, $word[0]);

Вы также можете получить доступ к каждой букве, используя фигурные скобки. Я использую следующий код для замены строчных символов с акцентированным лаком на верхний регистр.

$word{0} = str_replace(
    array('ą', 'ż', 'ś', 'ź', 'ę', 'ć', 'ł', 'ó', 'ń'), 
    array('Ą', 'Ż', 'Ś', 'Ź', 'Ę', 'Ć', 'Ł', 'Ó', 'Ń'), $word{0}
);
2

Чтобы развернуть ответ @renocor, я написал функцию, которая на 100% обратно совместима с str_replace(). То есть вы можете заменить все вхождения 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;

    }

}
  • 4
    вроде раздутый, если вы спросите меня. Также больше всего я ненавижу в этом решении - обработку ошибок. Это нарушает сценарий, если вы передаете неправильные значения. Вы думаете, что это выглядит профессионально, но это не так, вместо ошибки вместо этого выдается уведомление или предупреждение. Лучше пропустить ерунду, вернуть вместо этого значение false или null и никогда не использовать обратную трассировку в такой функции. Лучшее решение состоит в том, что программист может решить, что делать, если вывод неправильный / неожиданный.
  • 0
    @Erwinus Здесь используется E_USER_WARNING , что является предупреждением , а не ошибкой . Функция обратного отслеживания чрезвычайно полезна, чтобы выяснить, какой код в первую очередь передает недействительные данные функции (что абсолютно необходимо для отслеживания ошибок в процессе производства). Что касается возврата $subject вместо false / null или выдачи ошибки, это был просто личный выбор для моего варианта использования. Чтобы соответствовать функциональности str_replace() , лучше всего было бы использовать подхватываемые фатальные ошибки (как str_replace() делает str_replace() при закрытии первых двух аргументов).
Показать ещё 4 комментария
1

Эта функция сильно вдохновлена ​​ответом @renocor. Это делает функцию многобайтового безопасного.

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

Вы можете использовать это:

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

Нашел этот пример из php.net

Использование:

$string = "Thiz iz an examplz";
var_dump(str_replace_once('z','Z', $string)); 

Вывод:

ThiZ iz an examplz

Это может немного снизить производительность, но это самое простое решение.

  • 0
    Если это выход, то какой смысл? Разве это не должно заменить только первые строчные буквы "z" заглавными буквами "Z"? Вместо того, чтобы заменить их все? Я думал, что это то, о чем мы говорили здесь ...
  • 0
    Мой плохой, он заменит только первое вхождение. Ред.
Показать ещё 1 комментарий
0
$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")

Есть еще одно дополнительное пространство, но в моем случае это не имело значения, как для backgound script.

  • 0
    Этот метод был предоставлен Toomuchphp еще в 2009 году ! Я снизил рейтинг, потому что ваш пост не добавляет исследователям никакой новой ценности. Прежде чем публиковать ответ, убедитесь, что ваше решение является уникальным для данной страницы и повышает ее ценность.
0

Вот простой класс, который я создал, чтобы обернуть наши слегка измененные функции str_replace().

Наша функция php:: str_rreplace() также позволяет вам выполнить обратную ограниченную str_replace(), которая может быть очень удобной при попытке заменить только конечный экземпляр X строки.

В этих примерах используются 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) );
    }
}
  • 0
    Ваш пост не добавляет ценности этой уже перенасыщенной странице. Ваше решение регулярных выражений дает сбой во многих дополнительных случаях, потому что вы использовали неправильный инструмент для экранирования символов в строке иглы. Доказательство неудачи: 3v4l.org/dTdYK Сильно одобренный и принятый в 2009 году ответ уже показывает правильное выполнение этой техники. Ваш второй метод не отвечает на заданный вопрос и уже был предоставлен oLinkWebDevelopment.
-2

Легко найти решение для замены только первой или первой пары экземпляров (путем предоставления значения count). Существует не так много решений для замены последней или последней пары экземпляров.

Возможно, что-то вроде str_replace ($ find, $replace, $subject, -3) должно заменить последние три экземпляра.

В любом случае просто предложение.

  • 4
    Зачем отвечать на вопрос предложением, если ответ был принят два года назад ?!
  • 0
    Также -3 не будет работать как параметр, потому что 4-й параметр является выходным, а не входным параметром. Было бы лучше, если вы протестируете то, что вы предлагаете, вместо того, чтобы публиковать код, который вылетает.
Показать ещё 1 комментарий
-3

Это мой первый ответ здесь, я надеюсь сделать это правильно. Почему бы не использовать четвертый аргумент функции str_replace для этой проблемы?

mixed str_replace ( mixed $search , mixed $replace , mixed $subject [, int &$count ] )

count: если оно прошло, это будет установлено на количество выполненных замен.


edit: Этот ответ неверен, поскольку 4-й параметр str_replace - это переменная, которой назначается количество выполненных замен. Это не соответствует preg_replace, который имеет 4-й параметр $limit и 5-й параметр &$count.

  • 0
    Четвертые аргументы будут установлены функцией str_replace () для количества выполненных замен. Вот почему вы получаете ошибку, когда передаете целое число, а не переменную.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню