Синтаксис для рекурсивного регулярного выражения в переполнении стека

Мне не хватает того, что заставляет меня отказываться от использования рекурсивного (? 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»). Ваш метод должен работать (стрибижев), но мне не удалось его реализовать, я все еще на нем.

1

Решение

Вам нужно использовать 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,

Код PHP:

$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 является полезным приложением в регулярных выражениях? а также Что хорошего в регулярном выражении?.

1

Другие решения

При использовании 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);

Или сделать что-то еще в обратном вызове. Чего ты пытаешься достичь?

0

По вопросам рекламы [email protected]