Исключение строки из регулярного выражения

Доброго времени суток.

PHP:
$content = "<h1>Задача</h1><h1>Решение</h1>";
$h1 = substr_count($content, '<h1');

$c = 0;

while ( $c < $h1 ) {

    $content = preg_replace(
        '/<h1(.*|)>(.*[^<a name].*)<\/h1>/', 
        '<h1$1>$2<a name="h1-'.$c.'"></a></h1>', 
        $content, 
        1 
    );

    $c++;

} 

echo $content;
Должно происходить следующее:
PHP:
<h1>Задача<h1>
Должно заменяться на:
PHP:
<h1>Задача
    <a name="h1-0"></a>
</h1>
После чего, в этом же выполнении, должно заменяться:
PHP:
<h1>Решение</h1>
На:
PHP:
<h1>Решение
    <a name="h1-1"></a>
</h1>
Но происходит:
PHP:
<h1>Задача</h1>
<h1>Решение</h1>
Заменяется на:
PHP:
<h1>Задача
    <a name="h1-0"></a>
    <a name="h1-1"></a>
</h1>
<h1>Решение</h1>
Подскажите, пожалуйста, как решить эту задачу? Чтобы на выходе получилось:
PHP:
<h1>Задача
    <a name="h1-0"></a>
</h1>
<h1>Решение
    <a name="h1-1"></a>
</h1>
 

Redjik

Джедай-мастер
Ты хочешь именно так решать задачу?
может подумаем как добиться, чтобы в $content - все приходило уже в том виде в котором надо?

ЗЫ. вообще preg_match_all, и цикл
 
Ты хочешь именно так решать задачу?
может подумаем как добиться, чтобы в $content - все приходило уже в том виде в котором надо?

ЗЫ. вообще preg_match_all, и цикл
Да. Не человеческий это труд.

Почему нельзя за счёт preg_replace решить эту задачу?
 

Redjik

Джедай-мастер
счетчика не будет, preg_replace заменяет все вхождения, в регулярку не всматривался, но у тебя два раза отображается, потому, что оба раза находит первое вхождение, то есть даже если ты все поправишь в регулярке, то на выходе получишь
PHP:
<h1>Задача
    <a name="h1-0"></a>
    <a name="h1-1"></a>
</h1>
<h1>Решение
    <a name="h1-0"></a>
    <a name="h1-1"></a>
</h1>
поэтому сначала через preg_match_all найди все, что нужно, а потом распихай уже полученные данные...

ЗЫ. но лучше кончено изначально данные нормально обрабатывать
 
счетчика не будет, preg_replace заменяет все вхождения, в регулярку не всматривался, но у тебя два раза отображается, потому, что оба раза находит первое вхождение, то есть даже если ты все поправишь в регулярке, то на выходе получишь
PHP:
<h1>Задача
    <a name="h1-0"></a>
    <a name="h1-1"></a>
</h1>
<h1>Решение
    <a name="h1-0"></a>
    <a name="h1-1"></a>
</h1>
поэтому сначала через preg_match_all найди все, что нужно, а потом распихай уже полученные данные...

ЗЫ. но лучше кончено изначально данные нормально обрабатывать
PHP:
$content = '<h1 align="center">Задача</h1><h1>Решение</h1><h1>Проверка</h1><h1>Послепроверка</h1>';
            
$content= preg_replace(
    '/<h1(.*|)>(.*[^<a].*)<\/h1>/U',
    '<h1$1>$2<a name="h1-0"></a></h1>', 
    $content, 
    1 
);

$content= preg_replace(
    '/<h1(.*|)>(.*[^<a].*)<\/h1>/', 
    '<h1$1>$2<a name="h1-1"></a></h1>', 
    $content, 
    1 
);

$content= preg_replace(
    '/<h1(.*|)>(.*[^<a].*)<\/h1>/', 
    '<h1$1>$2<a name="h1-2"></a></h1>', 
    $content, 
    1 
);
        
$content= preg_replace(
    '/<h1(.*|)>(.*[^<a].*)<\/h1>/', 
    '<h1$1>$2<a name="h1-3"></a></h1>', 
    $content, 
    1 
);

echo $content;
На выходе получается:
PHP:
<h1 align="center">Задача
    <a name="h1-0"></a>
</h1>
<h1>Решение</h1>
<h1>Проверка</h1>
<h1>Послепроверка
    <a name="h1-1"></a>
    <a name="h1-2"></a>
    <a name="h1-3"></a>
</h1>
Почему так? На ощупь двигаюсь. Постараюсь сделать как ты посоветовал, спасибо.

Не совсем понятно мне, что значит "Лучше конечно изначально данные нормально обрабатывать". Можешь подробней? Чувствуется твое нежелание объяснять, но всё же, проблема в несовершенстве регулярных выражений и не желании доверять эту ответственность машине? Ведь в $content действительно могут быть очень объёмные данные, то есть ещё и нагрузка на сервер.
 

Ярослав

Новичок
Сергей Савельев

PHP:
$c = 0;
$result = preg_replace_callback(регулярка, function($matches) use (& $c) {

    заменяем
    $c++;
    возвращаем
} , строка где делаем замены)
В регулярке отключай жадность, через *? или модификатором U
 
Сергей Савельев

PHP:
$c = 0;
$result = preg_replace_callback(регулярка, function($matches) use (& $c) {

    заменяем
    $c++;
    возвращаем
} , строка где делаем замены)
В регулярке отключай жадность, через *? или модификатором U
Спасибо, мне понятно лишь одно, то что есть множество других, более подходящих для меня, в данной ситуации, вариантов. Буду учиться.
 
Сверху