За последние 24 часа нас посетили 19777 программистов и 1694 робота. Сейчас ищут 1848 программистов ...

Не получается уменьшить жадность квантификатора

Тема в разделе "Регулярные выражения", создана пользователем www, 8 июн 2009.

  1. www

    www Активный пользователь

    С нами с:
    8 июн 2009
    Сообщения:
    6
    Симпатии:
    0
    Здравствуйте, уважаемые!
    Несколько дней пытаюсь решить одну проблему. К сожалению, безуспешно.
    Изложу суть на простом примере.

    При помощи шаблона #b(\s+\S+)* ddd aa#U
    в строке bbb ccccc b vvv ddd aaaaaa
    надо найти выделенную подчеркиванием подстроку.

    С учетом того, что я использую модификатор U, проблем не должно возникнуть. Однако, указанный модификатор не оказывает должного влияния на конструкцию (\s+\S+)*, которая все равно остается жадной. В результате, при использовании указанного шаблона возвращается строка b ccccc b vvv ddd aa, а не b vvv ddd aa

    На форуме нашел описание похожей проблемы непослушной жадности. Но решения там нет.
    Как выше уже сказал, пытаюсь решить проблему уже несколько дней. Причем, наибольший интерес представляет уже именно теоретическая часть проблемы. Почему не получается уменьшить жадность? Либо это баги в самом PCRE, либо это у меня знаний не хватает.
    Заранее благодарен, если кто-то прольет свет на проблему.
    С Уважением, Алексей.
     
  2. Apple

    Apple Активный пользователь

    С нами с:
    13 янв 2007
    Сообщения:
    4.984
    Симпатии:
    2
    Короче хрен что поймешь.
    Наверняка на практике строка отличается от "bbb ccccc b vvv ddd aaaaaa".
    Нормальным русским языком сформулируйте правило что и где найти, а не aaa, bbb, vvv.
    Например, найти строку, которая начинается с буквы "В" за которой следует пробел и строка" — вот ТАК ВОТ.
    Сформулируйте правило, а там разберемся с проблемой, а гадать vvv и bbcc никто не будет.
     
  3. www

    www Активный пользователь

    С нами с:
    8 июн 2009
    Сообщения:
    6
    Симпатии:
    0
    Нет, "на практике" я как раз и экспериментировал с такой строкой, чтобы понять, почему не получается снизить жадность конструкции (\s+\S+)*


    Ок, давайте я еще раз сформулирую.
    Итак, я столкнулся с тем, что конструкция (\s+\S+)* игнорирует оба способа инвертации жадности своих квантификаторов (модификатор U и знак вопроса сразу после квантификатора). Мне надо понять причину подобного игнорирования.


    Решить конкретную проблему, если правило сформулировано, мне под силу. Согласитесь, сложного в этом нет ничего и много ума не надо, если внимательно прочесть документацию. Мой же случай, наукой не описан, как я понял.

    Если обязательно нужен конкретный пример, то он есть по приведенной в моем предыдущем сообщении ссылке:

     
  4. Apple

    Apple Активный пользователь

    С нами с:
    13 янв 2007
    Сообщения:
    4.984
    Симпатии:
    2
    Ваш случай наукой не описан, это обычное поведение и описано оно в документации.
    Поведение абсолютно такое, каким оно должно быть на практике:
    Регулярное выражение захватывает первый и последний тег, если указываете жадность, то захватывает первый и первый закрывающийся.
    Поведение самое нормальное и документированное, никакой паранормальности тут нет и жадность (а также её уменьшение работает).
    Проблема в том, что вы, видимо, плохо понимаете принцип работы регулярных выражений.

    Нужно правильно получить вложенную строку по последнему вхождению открытого тега.
    Решение буквально недавно где-то я писал.
     
  5. www

    www Активный пользователь

    С нами с:
    8 июн 2009
    Сообщения:
    6
    Симпатии:
    0
    Естественно, это более вероятно, чем баг в PCRE :)

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

    Ок, сейчас попробую найти.
     
  6. www

    www Активный пользователь

    С нами с:
    8 июн 2009
    Сообщения:
    6
    Симпатии:
    0
    Насколько я понял, найти у меня не получилось. Но, в принципе, мне понятно, о чем Вы - надо найти какой-нибудь уникальный признак у последнего открывающего тега и прицепиться к этому признаку, чтобы в качестве первого захваченного регулярным выражением тега был этот самый "последний открывающий тег".
    А средств заставить машину по умолчанию выбрать не первый открывающий тег, а последний, у нас нет. И регулировкой жадности тут не поможешь. Я правильно понял?
     
  7. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    (\s+\S+)*?
    не?
     
  8. www

    www Активный пользователь

    С нами с:
    8 июн 2009
    Сообщения:
    6
    Симпатии:
    0
    не, я ж написал:
     
  9. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
  10. www

    www Активный пользователь

    С нами с:
    8 июн 2009
    Сообщения:
    6
    Симпатии:
    0
    TheShock, это все понятно (кстати, по ссылке уже ходил, когда искал). Но меня больше занимает вопрос решения проблемы через конструирование корректного шаблона. Сейчас попробовал еще раз поискать по рунету алгоритмы работы парсера регулярных выражений (в частности, квантификаторов). Устраивающего не нашел. Буду благодарен, если разъясните. Вот как я теперь понимаю (спасибо Apple-у):
    Поиск первого символа шаблона идет в строке слева на право. После того, как первый символ шаблона обнаружен в строке, ищется совпадение остальных конструкций шаблона. И, если совпадение остальных конструкций шаблона найдено, на этом процесс выбора отправной точки (первого обнаруженного символа) заканчивается. Если сделать квантификаторы не жадными, то это не заставит алгоритм попытаться найти другую отправную точку ближе к концу строки.
    Вероятно, в подобном устройстве алгоритма есть своя логика. Но вот логика отсутствия средства заставить алгоритм искать новую отправную точку от меня ускользает.
     
  11. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    я как-то делал блочный шаблонизатор. впринципе, там стояла такая же проблема. при этом, надо было выводить ошибку, скажем, незакрытого блочного тега, или ошибку в имени переменной, потому я сделал расширенный парсер. могу показать код
     
  12. Sergey89

    Sergey89 Активный пользователь

    С нами с:
    4 янв 2007
    Сообщения:
    4.796
    Симпатии:
    0
    PHP:
    1. <?php
    2. $s = 'в строке bbb ccccc b vvv ddd aaaaaa';
    3. preg_match('#aa ddd (\S+\s+)*b#U', strrev($s), $m);
    4. print strrev($m[0]);
    хак :)
     
  13. TheShock

    TheShock Активный пользователь

    С нами с:
    30 май 2009
    Сообщения:
    1.255
    Симпатии:
    0
    Адрес:
    Київ
    извини, но это не хак, а костыль. :)