проблемы с рекурсией в PCRE (php)

Discussion in 'PHP' started by slesh, 11 Feb 2009.

  1. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    очень срочно нужно написать регулярное выражение чтобы отпарсить определенную строку. Сложность в том что каждая подстрока имеет еще другую последовательность разной длинны.
    Примерно вот
    HTML:
    <div>
    <h1>STR_1<h1>
      <h2>STR_2</h2>
       <ol>
         <li> STR_3
         <li> STR_4
         <li> STR_5
       </ol>
    </div>
    
    <div>
    <h1>STR_1<h1>
      <h2>STR_2</h2>
       <ol>
         <li> STR_3
         <li> STR_4
         <li> STR_5
         <li> STR_6
         <li> STR_7
       </ol>
    </div>
    
    вот мне нужно отпарсить и получить все данные на месте помеченным STR_
     
  2. Pashkela

    Pashkela Динозавр

    Joined:
    10 Jan 2008
    Messages:
    2,750
    Likes Received:
    1,044
    Reputations:
    339
    Почему у тебя тег <li> не закрыт </li>??? Уже припарился я
     
    1 person likes this.
  3. Gifts

    Gifts Green member

    Joined:
    25 Apr 2008
    Messages:
    2,494
    Likes Received:
    807
    Reputations:
    614
    slesh Тут рекурсивные регулярки НЕ нужны (только замедлят), вначале получаем все что между дивов, а потом уже получаем все STR

    PHP:
    <pre><?
    $in
    =<<<HTT
    <div>
    <h1>STR_1a</h1>
      <h2>STR_2a</h2>
       <ol>
         <li> STR_3a
         <li> STR_4a
         <li> STR_5a
       </ol>
    </div>

    <div>
    <h1>STR_1b</h1>
      <h2>STR_2b</h2>
       <ol>
         <li> STR_3b
         <li> STR_4b
         <li> STR_5b
         <li> STR_6b
         <li> STR_7b
       </ol>
    </div>
    HTT;
    //echo $in;
    preg_match_all('~<div>(.+)</div>~Usi',$in,$result);
    foreach(
    $result[1] as $i => $one)
    {
        
    // Получсаем заголовки
        
    preg_match('~<h1>([\s\S]*)</h1>\s*<h2>([\s\S]*)</h2>~Ui',$one,$head);
        
    // Выдираем все элементы списка
        
    preg_match_all('~<li> ([^\r\n]*)~i',$one,$tmp);
        echo 
    '<hr>'.$head[1].'<hr>'.$head[2].'<hr>';
        
    print_r($tmp[1]);
    }
    ?>
     
    _________________________
    1 person likes this.
  4. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    2 Pashkela: Как есть так есть. Да и вообщето </li> - необязателен (читай доки ;))
    2 Gifts: спс за код. Просто думал что возможно это сделать в один проход :)
     
  5. Chaak

    Chaak Elder - Старейшина

    Joined:
    1 Jun 2008
    Messages:
    1,059
    Likes Received:
    1,067
    Reputations:
    80
    Ну вы пиздецы..

    PHP:
    preg_match_all("#<li>(.*?)(\n|<)#i",$text,$res); 
    print_r($res);
    не рулит?
     
    #5 Chaak, 11 Feb 2009
    Last edited: 11 Feb 2009
  6. .:EnoT:.

    .:EnoT:. Сексуальное чудовище

    Joined:
    29 May 2007
    Messages:
    803
    Likes Received:
    559
    Reputations:
    50
    Можно и одним проходом, главное составить нужную регулярку. Если бы у тебя тег li был закрыт, то регулярка выглядела бы так:

    PHP:
    <?php

    $str 
    = <<<STR

    <div>
    <h1>STR_1a</h1>
      <h2>STR_2a</h2>
       <ol>
         <li> STR_3a</li>
         <li> STR_4a</li>
         <li> STR_5a</li>
       </ol>
    </div>

    <div>
    <h1>STR_1b</h1>
      <h2>STR_2b</h2>
       <ol>
         <li> STR_3b</li>
         <li> STR_4b</li>
         <li> STR_5b </li>
         <li> STR_6b</li>
         <li> STR_7b</li>
       </ol>
    </div>

    STR;


    preg_match_all('#<(h[12]{1}|li)>([^>]*)</\\1>#s'$str$out);
    print_r($out[2]);

    ?>

    Или если всё таки они не закрыты, то парсим вот так:

    PHP:
    <?php

    $str 
    = <<<STR

    <div>
    <h1>STR_1a</h1>
      <h2>STR_2a</h2>
       <ol>
         <li> STR_3a
         <li> STR_4a
         <li> STR_5a
       </ol>
    </div>

    <div>
    <h1>STR_1b</h1>
      <h2>STR_2b</h2>
       <ol>
         <li> STR_3b
         <li> STR_4b
         <li> STR_5b
         <li> STR_6b
         <li> STR_7b
       </ol>
    </div>

    STR;


    preg_match_all("#<(h[12]{1}|li)>([^>]*)(</h[12]{1}>|\r\n)#s"$str$out);
    print_r($out[2]);

    ?>

    Хитрый финт ушами))
     
    1 person likes this.
  7. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    2 ChaaK скажено же что нужно не только то, что в LI но и заголовки.
    И вообще эта тема уже неактуально ибо строчность уже пропала.
     
  8. .:EnoT:.

    .:EnoT:. Сексуальное чудовище

    Joined:
    29 May 2007
    Messages:
    803
    Likes Received:
    559
    Reputations:
    50
    не рулит, т.к. ему нужно получить текст не только между тегами LI, но и между дивами