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, $ substitu, $ pos, strlen ($ search)); повернути $ предмет; } else {return false; }
Джазі

4
@Jason Це не повертається TRUEнезалежно від того. Він повертає рядок незалежно від того. Якщо заміну неможливо зробити, він повертає оригінал $subject, як substr_replace і str_replaceробити.
Mischa

@Mischa Це не те саме в цьому випадку? Я намагався зробити щось на кшталт! Str_lreplace, але якщо воно не повертає помилку, це вважається правдою, правда? Так чи інакше, це мені допомогло, і я ціную це. Дякую.
Джазі

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, які одні і ті ж функції. (Але чи мали вони змінити ім’я?)
alexis

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

Чому це працює з усіма перетвореними рядками? Чи є певний (припускаю) певний приріст продуктивності при використанні регулярних виразів?
Камафезер

Ні, це насправді знижує продуктивність, але це тому, що ви хочете лише останнього явища, щоб ви обмежили пошук одним і скасували все, якщо хотіли б першого, вам не доведеться нічого перевертати
Tofandel

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

Дійсно, код, який я опублікував, змінює всі екземпляри "лисиці", окрім останнього, на "собаку", але те, що ми хочемо, якраз навпаки. Дякую, що вказали, що замінити? = На ?! виправляє проблему.
Джон Сондерсон

11

Ви можете це зробити:

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

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

З повагою


4
Це працює до тих пір, поки не буде повторених символів. У моїй ситуації я знімаю номер сторінки за датою архіву, тому у мене є "2015-12 / 2", і це означає, що всі / і всі 2 закінчуються, стаючи "2015-1".
Майк

Це буде працювати лише в тому випадку, якщо останнє пошукове явище є останнім словом і не має додаткових символів після нього.
AwesomeGuy

Це не працює, оскільки rtrimне веде себе так, як ти думаєш. З кінця буде викреслено будь-які символи, які існують у рядку пошуку в будь-якому порядку (і завжди додавати заміну), наприклад "Привіт слово" -> "Привіт Джон", "Привіт лорд" -> "Привіт Джон", "Привіт мотор "->" Привіт motJohn "," Привіт, світлий "->" Привіт worldyJohn ".
Джейк

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 ("х", "у", "цей х чи той х"); => Вихід: "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
Дякую! Ідеальна функція обернутись моїм виразом, щоб досягти цього. У моєму випадку я замінюю останню кому на ",". Радий, що я трохи прокрутився в цьому списку відповідей.
rlhane

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;

Вихід: малюнок_0007.значення


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, щоб ви могли замінити з правого боку за допомогою regex.

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.