Как заменить только последнее совпадение строки с preg_replace? - PullRequest
6 голосов
/ 17 октября 2011

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

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

Спасибо.

Ответы [ 4 ]

17 голосов
/ 17 октября 2011

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

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

вывод:

text abcd text bar efgh
1 голос
/ 25 июня 2018

Общий подход для сопоставления всего текста с последним вхождением последующего шаблона (ов) - это использование жадной точки , .*. Таким образом, вы можете сопоставить и захватить текст перед последним 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 и regex demo .

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

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

0 голосов
/ 15 марта 2018

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

Первая строка:

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

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

0 голосов
/ 17 октября 2011

Пример

<?php

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

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

print $results[0];

?> 
...