PHP заменить последнее вхождение строки в строке?


Ответы:


228

Вы можете использовать эту функцию:

function str_lreplace($search, $replace, $subject)
{
    $pos = strrpos($subject, $search);

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

    return $subject;
}

Это все еще возвращалось правда, несмотря ни на что. Попробуйте изменить его следующим образом: if ($ pos) {$ subject = substr_replace ($ subject, $ replace, $ pos, strlen ($ search)); вернуть $ субъект; } else {return false; }
Джаззи

4
@ Джейсон Это не вернется TRUEни на что. Он возвращает строку, несмотря ни на что. Если замена не может быть произведена, она возвращает оригинал $subject, как substr_replace и str_replaceделает.
Миша

@ Миша Разве это не то же самое в этом случае? Я пытался сделать что-то вроде! Str_lreplace, но если он не возвращает false, это считается верным, верно? В любом случае, это помогло мне, и я ценю это. Спасибо.
Джаззи

1
Как это может работать? strpos — Find the position of the first occurrence of a substring in a string- редактировать: вау. Php гении действительно сделали функцию под названием strposи strrpos? Спасибо ....
BarryBones41

1
@Barry это один случай , когда PHP не заслуживает вину :-) Имена узорной на многие десятилетия strstr, strrstrиз стандартной библиотеки C, которые одни и те же функции. (Но они должны были изменить имя?)
Алексис

30

Еще 1 вкладыш, но без прега:

$subject = 'bourbon, scotch, beer';
$search = ',';
$replace = ', and';

echo strrev(implode(strrev($replace), explode(strrev($search), strrev($subject), 2))); //output: bourbon, scotch, and beer

3
FWIW, принятое решение примерно на 35% быстрее, чем это решение.
JustCarty

27
$string = 'this is my world, not my world';
$find = 'world';
$replace = 'farm';
$result = preg_replace(strrev("/$find/"),strrev($replace),strrev($string),1);
echo strrev($result); //output: this is my world, not my farm

Самое крутое решение на мой взгляд и до сих пор легко понять.
Blackbam

Почему это работает со всеми перевернутыми строками? Есть ли какой-то (я полагаю) определенный прирост производительности при использовании регулярных выражений?
Kamafeather

Нет, это на самом деле снижает производительность, но это потому, что вы хотите только последнее вхождение, поэтому вы ограничиваете поиск до одного и полностью изменяете все, если вы хотите первое, вам не нужно ничего
менять

15

Следующее довольно компактное решение использует положительное предварительное утверждение PCRE для соответствия последнему вхождению интересующей подстроки, то есть вхождению подстроки, за которым не следуют другие вхождения той же подстроки. Таким образом, пример заменяет last 'fox'с 'dog'.

$string = 'The quick brown fox, fox, fox jumps over the lazy fox!!!';
echo preg_replace('/(fox(?!.*fox))/', 'dog', $string);

ВЫВОД: 

The quick brown fox, fox, fox jumps over the lazy dog!!!

5
Идея хорошая, а код - нет. Это должно быть:$string = 'The quick brown fox, fox, fox jumps over the lazy fox!!!'; echo preg_replace('/(fox(?!.*fox))/', 'dog', $string);
Ремер

Действительно, код, который я разместил, изменяет все экземпляры «fox», кроме последнего, на «dog», но мы хотим с точностью до наоборот. Спасибо, что указали на замену? = На?! устраняет проблему
Джон Сондерсон

11

Вы могли бы сделать это:

$str = 'Hello world';
$str = rtrim($str, 'world') . 'John';

Результат «Привет Джон»;

С уважением


4
Это работает до тех пор, пока нет повторяющихся символов. В моей ситуации я убираю номер страницы с даты архива, поэтому у меня "2015-12 / 2", и все / и все 2 с конца становятся "2015-1".
Майк

Это будет работать только в том случае, если последнее найденное вхождение является последним словом и не имеет дополнительных символов после него.
AwesomeGuy

Это не работает, потому rtrimчто не ведет себя так, как вы думаете. Он удалит с конца любые символы, которые существуют в строке поиска в любом порядке (и всегда добавляют замену), например, «Hello word» -> «Hello John», «Hello lord» -> «Hello John», «Hello мотор "->" Привет, motJohn "," Привет, мир "->" Привет, мирyJohn ".
Джейк

5

Это также будет работать:

function str_lreplace($search, $replace, $subject)
{
    return preg_replace('~(.*)' . preg_quote($search, '~') . '(.*?)~', '$1' . $replace . '$2', $subject, 1);
}

ОБНОВЛЕНИЕ Чуть более краткая версия ( http://ideone.com/B8i4o ):

function str_lreplace($search, $replace, $subject)
{
    return preg_replace('~(.*)' . preg_quote($search, '~') . '~', '$1' . $replace, $subject, 1);
}

Я делаю это неправильно? Если так, просто игнорируй меня :) ||| echo str_lreplace ("x", "y", "this x или that x"); => Вывод: "y" См .: ideone.com/UXuTo
edorian

@edorian: Ой! Извините, я спешил опубликовать, правильная версия здесь: ideone.com/vR073 .
Аликс Аксель

5

Всего одна строка кода (поздний ответ, но его стоит добавить):

$string = 'The quick brown fox jumps over the lazy dog';
$find_me = 'dog';

preg_replace('/'. $find_me .'$/', '', $string);

окончание $ указывает на конец строки.


5

Это древний вопрос, но почему все упускают простейшее решение на основе регулярных выражений? Нормальные кванторы регулярных выражений жадные люди! Если вы хотите найти последний экземпляр шаблона, просто вставьте .*перед ним. Вот как:

$text = "The quick brown fox, fox, fox, fox, jumps over etc.";
$fixed = preg_replace("((.*)fox)", "$1DUCK", $text);
print($fixed);

Это заменит последний экземпляр «fox» на «DUCK», как это должно быть, и напечатает:

The quick brown fox, fox, fox, DUCK, jumps over etc.

1
Спасибо! Идеальная функция, чтобы обернуть мое выражение лица, чтобы выполнить это. В моем случае я заменяю последнюю запятую на "и". Рад, что прокрутил немного в этом списке ответов.
Релан

3
$string = "picture_0007_value";
$findChar =strrpos($string,"_");
if($findChar !== FALSE) {
  $string[$findChar]=".";
}

echo $string;

Помимо ошибок в коде, у Фарука Унала есть лучший ответ. Одна функция делает свое дело.


Вам необходимо проверить, не является ли $ findChar ложным (так же, как в принятом ответе). Если строка не содержит искомой строки, вы получите уведомление, и первый символ будет заменен.
мохнатый

Это замечательно, но в его нынешнем виде он может заменить только 1 символ на 1 символ.
Пит

3

Вы можете использовать strrpos (), чтобы найти последнее совпадение.

$string = "picture_0007_value";
$findChar =strrpos($string,"_");

$string[$findChar]=".";

echo $string;

Вывод: picture_0007.value


2

Сокращение для принятого ответа

function str_lreplace($search, $replace, $subject){ 
    return is_numeric($pos=strrpos($subject,$search))?
    substr_replace($subject,$replace,$pos,strlen($search)):$subject;
}


0

Используйте «$» в выражении reg, чтобы соответствовать концу строки

$string = 'The quick brown fox jumps over the lazy fox';
echo preg_replace('/fox$/', 'dog', $string);

//output
'The quick brown fox jumps over the lazy dog'

4
это работает, только если последний вхождение находится в конце строки ideone.com/nbNSNq
cawecoy

1
Это не будет работать, если после последнего «лиса» появятся другие символы.
Джон Сондерсон

0

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

function preg_rreplace($search, $replace, $subject) {
    preg_match_all($search, $subject, $matches, PREG_SET_ORDER);
    $lastMatch = end($matches);

    if ($lastMatch && false !== $pos = strrpos($subject, $lastMatchedStr = $lastMatch[0])) {
        $subject = substr_replace($subject, $replace, $pos, strlen($lastMatchedStr));
    }

    return $subject;
}

Или как сокращенная комбинация / реализация обоих вариантов:

function str_rreplace($search, $replace, $subject) {
    return (false !== $pos = strrpos($subject, $search)) ?
        substr_replace($subject, $replace, $pos, strlen($search)) : $subject;
}
function preg_rreplace($search, $replace, $subject) {
    preg_match_all($search, $subject, $matches, PREG_SET_ORDER);
    return ($lastMatch = end($matches)) ? str_rreplace($lastMatch[0], $replace, $subject) : $subject;
}

на основе https://stackoverflow.com/a/3835653/3017716 и https://stackoverflow.com/a/23343396/3017716

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.