Регулярка: не могу справиться с жадностью

Syn23

Новичок
Доброго времени суток!!
Появилась преграда на пути к решению задачи, завела в тупик и не даёт покоя.
Вкратце суть задачи: у нас есть список:
HTML:
<ul>
    <li>
        <a href="#o">Первый</a>
    </li>
    <li>
        <a href="#v">Второй</a>
    </li>
    <li>
        <a href="#t">Третий</a>
    </li>
    <li>
        <a href="#ch">Четвертый</a>
    </li>
    <li>
        <a href="#p">Пятый</a>
    </li>
    <li>
        <a href="#test">Шестой</a>
        <ul>
            <li>
                <a href="#so">ШестьОдин</a>
            </li>
            <li>
                <a href="#sd">ШестьДва</a>
            </li>
            <li>
                <a href="#st">ШестьТри</a>
            </li>
            <li>
                <a href="#sc">ШестьЧетыре</a>
            </li>
            <li>
                <a href="#sp">ШестьПять</a>
            </li>
            <li>
                <a href="#ss">ШестьШесть</a>
            </li>
            <li>
                <a href="#sss">ШестьСемь</a>
            </li>
            <li>
                <a href="#sv">ШестьВосемь</a>
            </li>
            <li>
                <a href="#sd">ШестьДевять</a>
            </li>
        </ul>
    </li>
</ul>
В один UL вложен второй UL. Цель получить текст ссылки в том LI в который вложен второй Ul.
Моя реализация с помощью следующей регулярки:
Код:
'/<a.*?>(.*?)<\/a><ul/uis'
Но в результате мы получаем следующий код:

HTML:
Первый</a>
    </li>
    <li>
        <a href="#v">Второй</a>
    </li>
    <li>
        <a href="#t">Третий</a>
    </li>
    <li>
        <a href="#ch">Четвертый</a>
    </li>
    <li>
        <a href="#p">Пятый</a>
    </li>
    <li>
        <a href="#test">Шестой</a>
Т.е. регулярка получает всё от первой ссылки до вложенного ul.
Прошу помощи, не могу справиться с этой задачей, пробовал разные варианты, результата не дало
 

ossorian

Новичок
Могу ошибаться в регулярках, но суть, уверен, скажу верную...
Вы что запрашиваете - то и получаете. Скорее всего в массиве будет несколько вар-тов ответа.
Что-такое /uis - вообще первый раз вижу.
Надо сделать что-то вроде
Код:
'/<ul>.*<ul>.*<a.*?>(.*?)<\/a>.*<\/ul>/'
 

riff

Новичок
Что-такое /uis - вообще первый раз вижу.
Это равносильно признанию, что ты не знаешь регулярные выражения.

Цель получить текст ссылки в том LI в который вложен второй Ul.
PHP:
if (preg_match('~<a(.+?)>.+</a>\s*<ul>~', $text, $out))
{
    //если строки, на самом деле, разбиты не так аккуратно, как в вопросе, то
    //~<a([^>]+)>[^<]+</a>\s*<ul>~
    echo $out[1];
}
p.s. Не надо пихать все возможные модификаторы (uis). Они нужны только там, где они нужны.
 
Последнее редактирование:

accido

Новичок
Профит тут: http://regex101.com/r/zK5cP5
Но зачем регулярками парсить хтмл?
Можно определить 3 момента:
1) действие регулярок не ограничивается только разметкой и xpath запросами. В похапе можно подкручивать регулярки и для более интересных вещей, т.е. скажем так для более продвинутой обработки строк.
2) это все же менее ресурсоемко, чем строить анализатор лексем, который вообще имеет смысл строить только для исполняемых макросов/скриптов/преобразователей и т.д. Скажем если вам не надо делать xslt преобразование то зачем????????? Возьмите регулярку она для этого и предназначена, и не зачем городить велосипеды с 8-ми циллиндровыми движками, когда есть готовая машина.
3) это более читабельно, конечно для тех кто изучил регулярки(с регулярками вы будете спать спокойно по ночам :):):))
 
Последнее редактирование:

accido

Новичок
А если вообще глобально зачем парсить - так просто обработка открытой информации. Ведь копирайт распространяется только на весь контент, а использование отдельных кусков абсолютно не нарушает копирайта. Это как с цитированием отрывка вырванного из контекста - копирайт автора не нарушается даже если вы не укажете его. Другое дело если вы не хотите присваивать себе такую цитату, тогда указание автора - это как-бы "а Вася Пупкин сказал ...". :)
 

HQ0

Новичок
accido, какой-то странный ответ на _зачем парсить хтмл регулярками_ -- _регулярки не ограничиваются разметкой_
Если мне надо просто разобрать один сайт, если я не пишу универсальную вещь на все случай жизни, как швейцарский нож, то я, пожалуй, буду использовать инструмент, который предназначен для разбора хтмл.

У меня автоматически не будет никаких проблем с жадностью регулярок, мне не надо дочитывать доки про рекурсивные регулярки...

Аргумент про меньшее потребление памяти интересный, но изначально плохой. Зачем думать про это, если проблемы еще нет?

Да, я, пожалуй, не буду разбирать регулярками хтмл до определенного момента.
 

accido

Новичок
accido, какой-то странный ответ на _зачем парсить хтмл регулярками_ -- _регулярки не ограничиваются разметкой_
Если мне надо просто разобрать один сайт, если я не пишу универсальную вещь на все случай жизни, как швейцарский нож, то я, пожалуй, буду использовать инструмент, который предназначен для разбора хтмл.

У меня автоматически не будет никаких проблем с жадностью регулярок, мне не надо дочитывать доки про рекурсивные регулярки...

Аргумент про меньшее потребление памяти интересный, но изначально плохой. Зачем думать про это, если проблемы еще нет?

Да, я, пожалуй, не буду разбирать регулярками хтмл до определенного момента.
если вы разбираете весь сайт, то прошу пожалуйста, делайте преобразование во что хотите путем разбора лексем.

Но тут случай не из вашей жизни, поэтому допускать утечки производительности на ровном месте, а потом искать узкие места, хорошо если в своем коде, а не чужом, просто не допустимо. Получается вы собираетесь микроскопом забивать гвозди, вместо того чтобы взять молоток и за 5 сек выполнить задание.
 

HQ0

Новичок
Окей, давайте попробуем разобраться и решить, что же всё-таки круче. В споре ведь рождается истина, да ? :)

Невалидный хтмл, незакрытые (или не там закрытые) теги, ошибки в атрибутах.
В итоге у нас получается регулярка, которая справляется со своим делом, парсит что надо, но она очень большая, неповоротливая и надо будет очень постараться, чтобы понять что она делает спустя месяц.

Регулярки прекрасный инструмент для разбора текста, но разбирать им невалидные хтмл документы — боль и разочарование.
 

Syn23

Новичок
Это равносильно признанию, что ты не знаешь регулярные выражения.


PHP:
if (preg_match('~<a(.+?)>.+</a>\s*<ul>~', $text, $out))
{
    //если строки, на самом деле, разбиты не так аккуратно, как в вопросе, то
    //~<a([^>]+)>[^<]+</a>\s*<ul>~
    echo $out[1];
}
p.s. Не надо пихать все возможные модификаторы (uis). Они нужны только там, где они нужны.
Большое спасибо, регулярка для не аккуратно разбитых строка помогла!!
 

AnrDaemon

Продвинутый новичок
Вы будете удивлены... легче сказать, чего в этой жизни НЕ бывает.
 
Сверху