Регулярное выражение смотрящее назад - чтоэто и как его сделать ?

Тема в разделе "Регулярные выражения", создана пользователем FidaSa, 29 апр 2016.

Модераторы: xpert13
  1. FidaSa

    FidaSa

    Регистр.:
    1 мар 2013
    Сообщения:
    509
    Симпатии:
    133
    Доброй ночи.

    Нужно для программы сделать регулярное выражение, для поиска определенного фрагмента в html коде.
    Сложность в том что код имеет похожую структуру, и поэтому надо использовать регулярное выражение смотрящее назад, что это с трудом представляю.

    Есть тут кто с головой и понимает ?

    Вот такой мануал гугл выдал -, но понятнее не стало!


    но как заставить регулярку искать справа, налево, не понятно!

    Пример кода схематично.

    <a class="spin" lalal54agla </a></div>
    <a class="spin" зззз45ззa </a></div>
    <a class="spin" pppp5ggp </a></div><ul class="zuk">
    <a class="spin" xezx455cg </a></div>
    <a class="spin" htrdg45rh </a></div><ul class="zuk">
    <a class="spin" lyy45yyyy </a></div>
    <a class="spin" la5f45fff45 </a></div><ul class="zuk">

    Нужно чтобы регулярка находила вот такие куски
    <a class="spin" la5f45fff45 </a></div><ul class="zuk">
    <a class="spin" htrdg45rh </a></div><ul class="zuk">
    <a class="spin" pppp5ggp </a></div><ul class="zuk">

    А вот такие не трогала:
    <a class="spin" lalal54agla </a></div>
    <a class="spin" зззз45ззa </a></div>
    <a class="spin" lyy45yyyy </a></div>
    <a class="spin" xezx455cg </a></div>
     
  2. dmx

    dmx

    Регистр.:
    22 июн 2011
    Сообщения:
    685
    Симпатии:
    601
    Код:
    <a.*?<ul\ class="zuk">
    
     
    Последнее редактирование: 29 апр 2016
    FidaSa нравится это.
  3. FidaSa

    FidaSa

    Регистр.:
    1 мар 2013
    Сообщения:
    509
    Симпатии:
    133
    Сорри, я тупанула, в примере разбила код на строки, хотя они должны быть все в одну строку, в этом то и сложность.

    Вот такой пример кода:

    <a class="spin" lalal54agla </a></div><a class="spin" зззз45ззa </a></div><a class="spin" pppp5ggp </a></div><ul class="zuk"><a class="spin" xezx455cg </a></div><a class="spin" htrdg45rh </a></div><ul class="zuk"><a class="spin" lyy45yyyy </a></div><a class="spin" la5f45fff45 </a></div><ul class="zuk">


    Нужно чтобы регулярка находила вот такие куски
    <a class="spin" la5f45fff45 </a></div><ul class="zuk">
    <a class="spin" htrdg45rh </a></div><ul class="zuk">
    <a class="spin" pppp5ggp </a></div><ul class="zuk">

    А вот такие не трогала:
    <a class="spin" lalal54agla </a></div>
    <a class="spin" зззз45ззa </a></div>
    <a class="spin" lyy45yyyy </a></div>
    <a class="spin" xezx455cg </a></div>
     
    dmx нравится это.
  4. dmx

    dmx

    Регистр.:
    22 июн 2011
    Сообщения:
    685
    Симпатии:
    601
    Код:
    <a\ class="spin"\ [a-z0-9]+\ </a></div><ul.*?"zuk">
    тогда может так, но ерунда
     
    FidaSa нравится это.
  5. FidaSa

    FidaSa

    Регистр.:
    1 мар 2013
    Сообщения:
    509
    Симпатии:
    133
    Неа, не пройдет, проблема в том, что эти части текста очень похожи, разница только на хвосте текста, поэтому невозможно установить интервал, стандартным способом, который смотрит вперед, так как у них начало и содержимое одинаковое, и отличается только окончание, и они еще в одной строке.

    Пришлось разбить на строки и подругому сделать, через задницу (как обычно:) ), но вопрос для меня актуален:

    Как заставить регулярное выражение "смотреть назад" ?

    Чтобы оно сначала искало текст "<ul class="zuk">" и от него, шло налево, в сторону начала кода, то есть "назад" до первого встретившегося текста
    "<a"
     
  6. lag

    lag

    Регистр.:
    13 окт 2014
    Сообщения:
    229
    Симпатии:
    305
    А если захват от <a до ближайшего </a></div><ul class="zuk">
    Код:
    <a((?!</a).)+</a></div><ul class="zuk">
    
    https://regex101.com/r/wU4eC6/1
     
    FidaSa нравится это.
  7. FidaSa

    FidaSa

    Регистр.:
    1 мар 2013
    Сообщения:
    509
    Симпатии:
    133
    Спасибо, но нужен захват от "<ul class="zuk">" , до ближайшего "<a", в левую сторону (то есть "назад" до первого встретившегося текста" <a")
     
  8. denverkurt

    denverkurt Denve®

    Регистр.:
    23 дек 2013
    Сообщения:
    723
    Симпатии:
    395
    во-первых у вас там открывающий тег A не закрыт. это может вводить в заблуждение. и вообще непонятно что такое la5f45fff45 - текст ссылки, анкор или какой то атрибут?
    во-вторых регулярные выражения не смотрят ни вперед ни назад. а лишь ищут текст согласно заданного вами шаблона
    если нужна ссылка перед UL, может попробовать так:
    Код:
    (<a.*?>(.*?)</a>)</div><ul class="zuk">
    если такой паттерн задать в функцию preg_match_all то она вернет массив, в которой будут и весь блок
    Код:
    <a...>...</a></div><ul class="zuk">
    и вся ссылка
    Код:
    <a...>...</a>
    и текст внутри ссылки
    <a...>...</a>
     
    penguen и warg нравится это.
  9. FidaSa

    FidaSa

    Регистр.:
    1 мар 2013
    Сообщения:
    509
    Симпатии:
    133
    Как так нету :) , а это тогда о чем Lookbehind
     
  10. lag

    lag

    Регистр.:
    13 окт 2014
    Сообщения:
    229
    Симпатии:
    305
    Ретроспективная проверка (?<= ), (?<! ) как раз выполняет просмотр назад, но сперва нужно уточнить для какой прграммы составляется выражение т.к. в большинстве реализаций устанавливается ограничение на длину текста при ретроспективной проверке.
    Код:
    (?<=(<a.+?</a></div>))<ul class="zuk">
    В Perl, PHP, Python такое не работает.
    Работает в языках платформы .NET например C#.
    Тестирование регулярок для .NET http://regexlib.com/RETester.aspx
    Самые жесткие правила действуют в Perl и Python, где ретроспективная проверка ограничивается строками фиксированной длины. Например, конструкции (?<!\w) и (?<!this|that) допустимы, a (?<!books?) и (?<!^\w+: ) запрещены, поскольку они могут совпадать с текстом переменной длины. В таких случаях, как с (?<!books?), задача решается выражением (?<!book)(?<!books), но понять его с первого взгляда весьма непросто.

    На следующем уровне поддержки в ретроспективной проверке допускаются альтернативы разной длины, поэтому выражение (?<!books?) может быть записано в виде (?<!book|books). PCRE (и все функции рreg в РНР) это позволяют.

    На следующем уровне допускаются регулярные выражения, совпадающие с текстом переменной, но конечной длины. Например, выражение (?<!books?) разрешено, а выражение (?<!^\w+: ) запрещено, поскольку совпадение \w+ может иметь непредсказуемую длину. Этот уровень поддерживается пакетом регулярных выражений для Java от Sun.

    Справедливости ради стоит заметить, что первые три уровня в действительности эквивалентны, потому что все они могут быть выражены, хотя и несколько громоздко, средствами минимального уровня (с фиксированной длиной). Остальные уровни – всего лишь «синтаксическая обертка», позволяющая сделать то же самое более удобным способом.
    Впрочем, существует и четвертый уровень, при котором подвыражение в ретроспективной проверке может совпадать с произвольным объемом текста, поэтому выражение (?<!^\w+: ) является разрешенным. Этот уровень, поддерживаемый языками платформы .NET от Microsoft, принципиально превосходит остальные уровни, однако его неразумное применение может серьезно замедлить работу программы (столкнувшись с ретроспективой, которая может совпадать с текстом произвольной длины, механизм вынужден проверять условие от начала строки, что требует огромного объема лишней работы при проверке в конце длинного текста).

    Поэтому предлагал решение задачи без использования (?<= ) https://www.nulled.in/threads/274479/#post-2572392
    Это выражение найдёт <ul class="zuk"> и захватит текст только до ближайшего слева "<a"
     
    Последнее редактирование: 30 апр 2016