Как заменить только последнее совпадение строки на preg replace?
Мне нужно заменить последнее совпадение строки (например, слово foo) в HTML-документе. Проблема в том, что структура HTML-документа всегда случайна.
Я пытаюсь сделать это с помощью preg_replace, но пока я знаю, как заменить только первое совпадение, но не последнее.
Спасибо.
4 answers
Используйте негативный уход (?!...)
$str = 'text abcd text text efgh';
echo preg_replace('~text(?!.*text)~', 'bar', $str),"\n";
Выход:
text abcd text bar efgh
Общий подход для сопоставления всего текста с последним вхождением последующего шаблона(ов) заключается в использовании жадной точки, .*
. Таким образом, вы можете сопоставить и записать текст до последнего 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
начинается с цифры.
Пример
<?php
$str = 'Some random text';
$str_Pattern = '/[^ ]*$/';
preg_match($str_Pattern, $str, $results);
print $results[0];
?>
Конечно, принятое решение, приведенное здесь, является правильным. Тем не менее, вы также можете захотеть взглянуть на этот пост . Я использую это там, где не требуется шаблон, и строка не содержит символов, которые не могут быть захвачены используемыми функциями (т. Е. многобайтовыми). Я также ввел дополнительный параметр для случая dis/в отношении.
Тогда первая строка:
$pos = $case === true ? strripos($subject, $search) : strrpos($subject, $search);
Я должен признать, что я не проверял производительность. Тем не менее, я предполагаю, что preg_replace() работает медленнее, особенно на больших строках.