Как заменить только последнее совпадение строки на preg replace?


Мне нужно заменить последнее совпадение строки (например, слово foo) в HTML-документе. Проблема в том, что структура HTML-документа всегда случайна.

Я пытаюсь сделать это с помощью preg_replace, но пока я знаю, как заменить только первое совпадение, но не последнее.

Спасибо.

Author: Dimitur Vulchanov, 2011-10-17

4 answers

Используйте негативный уход (?!...)

$str = 'text abcd text text efgh';
echo preg_replace('~text(?!.*text)~', 'bar', $str),"\n";

Выход:

text abcd text bar efgh
 16
Author: Toto, 2011-10-17 09:17:25

Общий подход для сопоставления всего текста с последним вхождением последующего шаблона(ов) заключается в использовании жадной точки, .*. Таким образом, вы можете сопоставить и записать текст до последнего text и заменить обратной ссылкой + новое значение:

$str = 'text abcd text text efgh';
echo preg_replace('~(.*)text~su', '${1}bar', $str);
// => text abcd text bar efgh

Если text является некоторым значением внутри переменной, которое должно обрабатываться как обычный текст, используйте preg_quote, чтобы убедиться, что все специальные символы экранированы правильно:

preg_replace('~(.*)' . preg_quote($text, '~') . '~su', '${1}bar', $str)

См. онлайн-демонстрация PHP и еще демонстрация регулярных выражений.

Здесь (.*) совпадает и записывает в группу 1 любые нулевые или более символов (обратите внимание, что модификатор s также позволяет символам разрыва строки совпадать с точкой), как можно больше, вплоть до крайнего правого (последнего) вхождения text. Если text является подстрокой в Юникоде, модификатор u пригодится в PHP (он включает (*UTF) глагол PCRE, позволяющий анализировать входящую строку как последовательность кодовых точек Юникода, а не байтов, и глагол (*UCP), который делает все классы сокращенных символов Юникода знают - если таковые имеются).

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

 1
Author: Wiktor Stribiżew, 2018-06-25 09:34:14

Пример

<?php

$str = 'Some random text';
$str_Pattern = '/[^ ]*$/';

preg_match($str_Pattern, $str, $results);

print $results[0];

?> 
 0
Author: ka_lin, 2011-10-17 08:56:48

Конечно, принятое решение, приведенное здесь, является правильным. Тем не менее, вы также можете захотеть взглянуть на этот пост . Я использую это там, где не требуется шаблон, и строка не содержит символов, которые не могут быть захвачены используемыми функциями (т. Е. многобайтовыми). Я также ввел дополнительный параметр для случая dis/в отношении.

Тогда первая строка:

$pos = $case === true ? strripos($subject, $search) : strrpos($subject, $search);

Я должен признать, что я не проверял производительность. Тем не менее, я предполагаю, что preg_replace() работает медленнее, особенно на больших строках.

 0
Author: meistermuh, 2018-03-15 14:00:52