Мне не хватает того, что заставляет меня отказываться от использования рекурсивного (? R).
Пример, чтобы объяснить мою проблему «ясно»:
$str1 = "somes text -start bla bla FIND bla bla bla FIND bla FIND bla end-";
$str2 = "somes text -start bla bla FIND bla bla bla FIND bla FIND bla end-";
$my_pattern = "-start .*(FIND).* end-";
preg_replace_callback($my_pattern, 'callback', $str1.$str2);
Это будет соответствовать только самому последнему НАЙДУ.
С опцией ‘ungreedy’ я сопоставлю 1-е НАЙТИ с $ str.
Но как я могу получить их все? Я пытался использовать ‘(? R)’, но я действительно не понимаю, как это работает.
Поблагодарить.
РЕДАКТИРОВАТЬ: настоящая работа заключается в том, чтобы найти все свойства ‘title’ между <a>
& </a>
,
Я знаю, что не оптимизировать использование регулярных выражений для анализа html, но это просто работа из школы, чтобы изучить регулярные выражения.
Вот почему я не ставил реальную работу, я хотел понять и быть в состоянии сделать это сам.
<html>
<head><title>Nice page</title></head>
<body>
Hello World
<a href=http://cyan.com title="a link">
this is a link
</a>
<br />
<a href=http://www.riven.com> Here too <img src=wrong.image title="and again">
<span>Even that<div title="same">all the same</div></span>
</a>
</body>
</html>
Моя работа слишком помещает все заголовки в верхний регистр (title = «A LINK», например), используя регулярные выражения.
Моя последняя модель была:
#<a .* title=\"(.*)\".*</a>#Uis
Заставил меня поймать (title = «ссылка») и (title = «and again»). Ваш метод должен работать (стрибижев), но мне не удалось его реализовать, я все еще на нем.
Вам нужно использовать DOMDocument с DOMXPath, чтобы безопасно получить все атрибуты заголовка и изменить их с помощью mb_strtoupper
:
$html = "<<YOUR_HTML>>";
$dom = new DOMDocument('1.0', 'UTF-8');
$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$xpath = new DOMXPath($dom);
$titles = $xpath->query('//a[@title]');
foreach($titles as $title) {
$title->setAttribute("title", mb_strtoupper($title->getAttribute("title"), 'UTF-8'));
}
echo $dom->saveHTML();
Увидеть IDEONE демо.
//a[@title]
xpath получает <a>
элементы (a
) с атрибутом title
,
я использую mb_strtoupper
при условии, что у вас есть вход UTF8. Пожалуйста, настройте соответственно, или, если вы не планируете использовать Unicode, просто используйте strtoupper
.
Вот регулярное выражение, которое позволит вам заменить все FIND
подстроки внутри -start
а также -end
:
(-start|(?!^)\G)(.*?)FIND(?=.*end-)
Увидеть демонстрация
Заменить $1$2NEW_WORD
,
$re = "#(-start|(?!^)\G)(.*?)FIND(?=.*end-)#";
$str = "somes text -start bla bla FIND bla bla bla FIND bla FIND bla end-";
$subst = "$1$2NEW_WORD";
$result = preg_replace($re, $subst, $str);
echo $result;
НОТА: Если у вас есть несколько start-end
блоки, вам, скорее всего, понадобится закаленный жадный жетон (?:(?!-start|end-|FIND).)*
вместо .*?
а также .*
,
Распределение регулярных выражений:
(-start|(?!^)\G)
— Эта группа содержит две альтернативы:
-start
— соответствует литеральной строке -start
(?!^)\G
— устанавливает позицию в исходной строке ввода сразу после последнего успешного совпадения. \G
Можно также утверждать начало строки, но мы исключаем ее с отрицательным прогнозом.(.*?)
— Подберите любое количество символов, но как можно меньшеFIND
— буквальная строка FIND
(?=.*end-)
— только если есть литеральная строка end-
после FIND
,Для получения дополнительной информации о \G
оператор, см. Когда \ G является полезным приложением в регулярных выражениях? а также Что хорошего в регулярном выражении?.
При использовании preg_replace_callback
почему бы не неохотный .*?
быть удобным.
$my_pattern = "/-start(.*?)end-/s";
$str = preg_replace_callback($my_pattern, function($matches) {
return str_replace("FIND", "<b>FIND</b>", $matches[0]);
}, $str1.$str2);
Или сделать что-то еще в обратном вызове. Чего ты пытаешься достичь?