У меня проблема с моим с str_ireplace в PHP [duplicate]

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

Вам понадобится хотя бы наивный алгоритм генерации (попробуйте Porter stemmer, есть доступный бесплатный код на большинстве языков) для обработки текста в первую очередь. Сохраните этот обработанный текст и предварительно обработанный текст в двух отдельных массивах с пространственным разделением. Убедитесь, что каждый не-алфавитный символ также получает свой собственный индекс в этом массиве. Какой бы ни был список слов, которые вы фильтруете, также используйте их.

Следующим шагом будет поиск индексов массива, которые соответствуют вашему списку слов «остановить». Удалите те из необработанного массива, а затем присоединитесь к пробелам.

Это немного сложнее, но будет гораздо более надежным подходом. Если у вас есть сомнения относительно ценности более ориентированного на NLP подхода, вам может потребоваться некоторое исследование ошибок clbuttic .

265
задан JakeGould 7 May 2014 в 16:51
поделиться

23 ответа

Можно выполнить с помощью 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'

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

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

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

278
ответ дан T.Todua 17 August 2018 в 09:15
поделиться
  • 1
    Недостатком этого метода является ограничение производительности регулярных выражений. – zombat 10 August 2009 в 03:42
  • 2
    Еще один недостаток заключается в том, что вы должны использовать preg_quote () для «иглы». и избежать метасимволов $ и \ в замене. – Josh Davis 10 August 2009 в 03:53
  • 3
    Это не удается в качестве общего решения из-за неприятных проблем с экранированием. – Jeremy Kauffman 9 July 2011 в 01:39
  • 4
    Слишком часто регулярные выражения отклоняются из-за «производительности», если производительность была главной задачей, мы бы не писали PHP! Для обертывания шаблона, возможно, «~» может быть использовано нечто иное, чем «/», которое в какой-то мере помогло бы избежать проблемы экранирования. Это зависит от данных и от того, откуда они взялись. – ThomasRedstone 12 December 2015 в 00:26
  • 5
    Снижение производительности в сторону - те, кто жалуются на проблемы с экранированием, имеют что-то конкретное, помимо потенциальных ошибок в preg_quote? Например, @ThomasRedstone опасается, что разделитель / может быть опасным, если он появляется в $from, но, к счастью, это не так: он правильно экранирован из-за второго параметра preg_quote (можно легко проверить это) , Мне было бы интересно узнать о конкретных проблемах (которые были бы серьезными ошибками в защите PCRE в моей книге). – MvanGeest 31 January 2017 в 03:30

К сожалению, я не знаю никакой функции 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));
}
51
ответ дан Alex Tartan 17 August 2018 в 09:15
поделиться

Вот простой класс, который я создал, чтобы обернуть наши слегка измененные функции 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
ответ дан Aran 17 August 2018 в 09:15
поделиться

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

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

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

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

454
ответ дан billynoah 17 August 2018 в 09:15
поделиться
  • 1
    Может быть намного быстрее и будет использовать меньше памяти, чем регулярные выражения. Не знаю, почему кто-то проголосует за это ... – Josh Davis 10 August 2009 в 03:54
  • 2
    Да, кто-то пришел и проголосовал за кучу ответов. Всегда классный ход. – zombat 10 August 2009 в 04:49
  • 3
    Мне нравится этот подход, но код имеет ошибку, последний параметр вызова substr_replace должен быть strlen ($ needle) вместо strlen ($ replace) .. будьте осторожны! – Nelson 21 September 2010 в 12:47
  • 4
    Я не согласен с @CamiloMartin в отношении количества строк и возможности ошибок. В то время как substr_replace является несколько громоздкой функцией, используемой в силу всех параметров, реальная проблема заключается в том, что выполнение строковых манипуляций по номерам бывает просто сложным иногда - вы должны быть осторожны, чтобы передать правильную переменную / смещение к функциям. Я на самом деле зашел так далеко, чтобы сказать, что приведенный выше код является самым простым и для меня логичным подходом. – Alex 22 April 2014 в 16:21
  • 5
    Блестящий подход. Прекрасно работает при замене значений переменных, в которых зарезервированы символы регулярных выражений (так что preg_replace - медведь). Это просто и элегантно. – Praesagus 7 November 2014 в 03:55

Эта функция сильно вдохновлена ​​ответом @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
ответ дан blablabla 17 August 2018 в 09:15
поделиться

Чтобы расширить ответ @ 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;

    }

}
63
ответ дан Community 17 August 2018 в 09:15
поделиться
  • 1
    если вы спросите меня. И то, что я больше всего «ненавижу» в этом решении, - это обработка ошибок. Он прерывает скрипт, если вы передадите неправильные значения. Вы думаете, что это выглядит профессионально, но вместо этого вместо ошибки возникает уведомление или предупреждение. Лучше пропустить ерунду, вернуть ложь вместо или null и никогда не использовать обратную линию в такой функции. Лучшее решение состоит в том, что программист может решить, что делать, когда результат неправильный / неожиданный. – Codebeat 16 July 2013 в 21:40
  • 2
    @Erwinus Использует E_USER_WARNING всюду, что является предупреждением , not ошибкой . Backtrace чрезвычайно полезен, чтобы узнать, какой код передаёт недействительные данные функции в первую очередь (что абсолютно необходимо для отслеживания ошибок при производстве). Что касается возврата $subject вместо false / null или появления ошибки, это был просто личный выбор для моего варианта использования. Для соответствия функциональности str_replace() использование уловимых фатальных ошибок было бы лучшим выбором (поскольку str_replace() делает это при условии закрытия первых двух аргументов). – 0b10011 17 July 2013 в 04:03
  • 3
    Ах, не заметил, что вы используете E_USER_WARNING, извините за это. Проблема с возвратом предмета заключается в том, что вы никогда не увидите, что что-то не так, вне функции. Тем не менее, функция может быть вдвое меньше, если вы сделаете это умнее (возможно). Во-вторых, комментарии прекрасны, когда они объясняют что-то сложное, но не очень полезное для простых вещей, таких как увеличение стоимости. В целом я думаю, что это не нужно огромным. Кроме того, использование предупреждений в рабочей среде может быть проблемой безопасности при использовании этого кода на сервере, который по умолчанию не запрещает сообщения во время выполнения (журналы). – Codebeat 17 July 2013 в 04:47
  • 4
    @Erwinus Я был многословным, когда дело доходило до комментариев, потому что некоторые люди не понимают язык так же хорошо, как и другие, и комментарии всегда могут быть удалены теми, кто его понимает. Если вы знаете лучший способ получить один и тот же конечный результат для всех случаев краев, обязательно отредактируйте ответ. И если ваша производственная среда не подавляет сообщения об ошибках, у вас есть большая проблема, чем эта функция;) – 0b10011 17 July 2013 в 04:58
  • 5
    Спасибо за это, я обычно использую preg_replace, поскольку он является наиболее гибким, если в будущем требуется настройка в большинстве случаев на 27% медленнее, не будет значительным – zzapper 28 January 2016 в 15:32
  • 6
    @oLinkWebDevelopment Мне будет интересно увидеть ваш тестовый сценарий. Я думаю, что это может оказаться полезным. – Dave Morton 7 April 2017 в 16:28

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

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

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

-4
ответ дан EJoshuaS 17 August 2018 в 09:15
поделиться
  • 1
    Зачем отвечать на вопрос с предложением, когда ответ был принят два года назад ?! – mbinette 29 October 2012 в 00:05
  • 2
    Также -3 не будет работать как параметр, потому что 4-й параметр выведен и не вводит параметр. Было бы лучше, если вы проверите то, что вы предлагаете, вместо отправки кода, который выйдет из строя. – Ghostwriter78 6 February 2015 в 03:15
  • 3
    Да, это неправильно, однако, почему я получаю пустой краш экрана, когда я пытаюсь? Я сделал обычный error_reporting (E_ALL); ini_set ("display_errors", 1); Ошибка пустого экрана. – Doug Cassidy 7 July 2015 в 20:25

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

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

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

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

86
ответ дан Gras Double 17 August 2018 в 09:15
поделиться
  • 1
    Четвертый аргумент будет установлен str_replace () на количество произведенных замен. Вот почему вы получаете сообщение об ошибке, когда передаете целое число, а не переменную. – arminrosu 8 January 2014 в 18:50
  • 2
    Почему бы не обобщать это как: str_replace_flexible (смешанные $ s, смешанные $ r, int $ offset, int $ limit), где функция заменяет $ limit, начиная со смещения $ offset (nth). – Adam Friedman 23 May 2014 в 20:09
  • 3
    Слишком плохо это относится только к случаям, чувствительным к регистру. – andreszs 20 March 2015 в 00:02
  • 4
    @Andrew stripos() на помощь :-) – Gras Double 13 February 2016 в 20:23

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

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

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

1
ответ дан happyhardik 17 August 2018 в 09:15
поделиться
  • 1
    Если это результат, чем то, что является точкой? Не следует ли это заменять только первую строчную букву «z»? с верхним регистром "Z" Вместо того, чтобы заменить их все? Я думал, это то, о чем мы говорили здесь ... – Swivel 11 March 2014 в 08:08
  • 2
    Мой плохой, он заменит только первое вхождение. Ред. – happyhardik 16 April 2014 в 11:39

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

Решение от 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 не так уж плоха, как думают многие. Поэтому я предлагаю классное решение, если ваш обычный экспресс не является сложным.

2
ответ дан Hunter Wu 17 August 2018 в 09:15
поделиться

Чтобы расширить ответ на зомбат (который, я считаю, лучшим ответом), я создал рекурсивную версию его функции, которая принимает параметр $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;
        }
    }
}
2
ответ дан jtate 17 August 2018 в 09:15
поделиться

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

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

$string[0] = "B";

echo $string;

«Borem ipsum lá lá lá»

3
ответ дан Leandro Castro 17 August 2018 в 09:15
поделиться
  • 1
    Если он не содержит многобайтовых символов ... а затем ваша техника не удалась. Как жаль, что вы предложили примерную строку ввода, содержащую á. Демонстрация отказа – mickmackusa 21 April 2018 в 06:41
  • 2
    Вы можете проверить, является ли ваш string многобайтовой строкой, используя mb_strlen($subject) != strlen($subject) – RousseauAlexandre 30 May 2018 в 09:05
$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.

0
ответ дан loqan 17 August 2018 в 09:15
поделиться
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));
}
3
ответ дан luchaninov 17 August 2018 в 09:15
поделиться

Для строки

$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
2
ответ дан oLinkWebDevelopment 17 August 2018 в 09:15
поделиться

Я создал эту функцию little , которая заменяет строку на строку (с учетом регистра) с лимитом, без необходимости в 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
5
ответ дан Parziphal 17 August 2018 в 09:15
поделиться
  • 1
    Хотя я предпочел бы ===false вместо is_bool( быть более явным - я даю этот большой палец вверх только потому, что он избегал безумия RegExp ! ... и в то же время он работает и clean решение ... – jave.web 14 March 2016 в 16:03

Если строка не содержит многобайтовых символов, и если вы хотите заменить только один символ, вы можете просто использовать strpos

Здесь функция, которая обрабатывает ошибки

/**
 * 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;
}
0
ответ дан RousseauAlexandre 17 August 2018 в 09:15
поделиться

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

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

Но i действительно будет для RegExp.

3
ответ дан Rufinus 17 August 2018 в 09:15
поделиться

Замена первого «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);
}
3
ответ дан talsibony 17 August 2018 в 09:15
поделиться
  • 1
    Не получается, если $ this имеет повторяющиеся символы, такие как aaa vs aaaaaaaaa – Cristo 13 June 2016 в 08:09
  • 2
    Я думаю, что это должно быть substr($where,$b+strlen($this)), а не substr($where,$b+1). И я предполагаю, что substr_replace работает быстрее. – Titus 21 November 2017 в 10:00
$string = 'this is my world, not my world';
$find = 'world';
$replace = 'farm';
$result = preg_replace("/$find/",$replace,$string,1);
echo $result;
3
ответ дан zack 17 August 2018 в 09:15
поделиться
  • 1
    Это то же самое, что и первый ответ. Кроме того, перед использованием в качестве выражения вы должны сделать preg_quote из $find. – Emil Vikström 21 June 2012 в 23:37
  • 2
    это то, что я использовал, поэтому я проголосовал за это. Первый ответ вызвал конфликт с Drupal, он должен был перезаписать вспомогательную функцию drupal. Поэтому я просто взял код, который был внутри функции, и использовал его в соответствии с остальной частью кода ... – Dan Mantyla 19 September 2017 в 21:23
63
ответ дан Community 6 September 2018 в 06:56
поделиться
87
ответ дан Gras Double 6 September 2018 в 06:56
поделиться
0
ответ дан Asimov 29 October 2018 в 13:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: