Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Тексты > Проблема с регулярным выражением


Автор: FireDemon 24.3.2008, 21:23
Есть регулярное выражение:
Код
/{([^:}]+)(:([^}]+))?(.*){\/\\1}/s


Есть шаблон который должен парсится:
Код

{greeting}

today is {date}, {name}

<p>{img:44e1a0769f22c81eabdb54c1585d24c8.jpeg:left}текст</p>

<table>{news:Новинки:3:<tr><td colspan=2><hr></td></tr>}
<tr valign=top>
<td rowspan=2>{img:{file}:width=150}</td>
<td><b>{newsname}</b></td>
</tr>
<tr>
<td height=100% valign=top>{descr}</td>
</tr>{/news}
</table>

{own_name}
{own_email}


В php4 все работало, а в php5 не работает.

Кто знает подскажите пожалуйста.

Автор: alexbess 24.3.2008, 22:50
может так будет работать?
Код

/\{([^:\}]+)(:([^\}]+))?(.*)\{\/\\1\}/s

Автор: ksnk 25.3.2008, 00:49
FireDemon, А что эта регулярка делала, когда она работала? ;-) Сейчас она выедает все между {news:... и  {/news}.
Разве что ее можно подправить вот так
Код

/{([^:}]+)(?:\:([^}]+))?(.*?){\/\\1}/s

чтобы убрать лишнюю захватывающую маску и ликвидировать ошибку со слишком жадным завершением...

Автор: FireDemon 25.3.2008, 10:08
Вот весь код функции:
Код

    function Tpl2Str($tpl, $entry =0, $task =0, &$used_files_catalog, $template =0, $vars =array()) 
    {
    $is_sample = !$entry;
    if($entry && is_int($entry)) $entry = load_row('address_book', "id=$entry");
    if(is_int($task)) $task = load_row('tasks', "id=$task");
    $tpl_entries = $vars+array('{greeting}' => "$entry[greeting]", 
                   '{date}' => date('d.m.Y'), 
                   '{own_name}' => $GLOBALS['config']['own_name'], 
                   '{own_email}' => $GLOBALS['config']['own_email'], 
                   '{name}' => $entry['name']);
    while(preg_match("/{([^:}]+)(:([^}]+))?}(.*){\/\\1}/s", $tpl, $m = array(), PREG_OFFSET_CAPTURE)) 
    switch(strtolower($m[1][0])) 
    {
        case "news":
        list($group, $max, $delimeter) = explode(':', $m[3][0]);
        $r ='';
        foreach($GLOBALS['DB']->Query("SELECT files_catalog.* FROM files_catalog LEFT JOIN files_catalog_groups_members ON files_catalog_groups_members.file=files_catalog.id ".
                      "LEFT JOIN files_catalog_groups ON files_catalog_groups_members.group=files_catalog_groups.id ".
                      "LEFT JOIN files_catalog_files ON files_catalog.id=files_catalog_files.file LEFT JOIN files ON files_catalog_files.fid=files.id ".
                      "WHERE files_catalog_groups.name='$group' ".($task?"AND files.tm_add>='$task[tm_last_send]' ":'').
                      "GROUP BY files_catalog.id ORDER BY files.tm_add DESC,files_catalog_files.id DESC".((int)$max>0?" LIMIT $max":'')) as $file_catalog) 
        {
        $r .= ($r!=''?$delimeter:'').SpamPage::Tpl2Str($m[4][0], $entry, $task, $used_files_catalog, $template, array("{file}"=>"#$file_catalog[id]", "{newsname}"=>$file_catalog['name'], "{descr}"=>$file_catalog['comment'])+$vars);
        $used_files_catalog[$file_catalog['id']]=1;
        }
        $tpl = substr_replace($tpl, $r, $m[0][1], strlen($m[0][0]));
        break;
    }
    $tpl = str_replace(array_keys($tpl_entries), array_values($tpl_entries), $tpl);
    if(preg_match_all("/{img:([^:}]+)(:([^}]+))?}/i", $tpl, $m = array(), PREG_SET_ORDER|PREG_OFFSET_CAPTURE)) foreach(array_reverse($m) as $t) 
    {
        if($t[1][0][0]=='#') 
        {
        $file = (int)substr($t[1][0], 1);
        if($is_sample) $url = mkfileurl($GLOBALS['DB']->Query("SELECT fid FROM files_catalog_files WHERE file=$file ORDER BY id DESC LIMIT 1", 1));
        else $url = "cid:".$GLOBALS['DB']->Query("SELECT files.filename FROM files LEFT JOIN files_catalog_files ON files_catalog_files.fid=files.id ".
                             "WHERE files_catalog_files.file=$file ORDER BY files_catalog_files.id DESC LIMIT 1", 1);
        } else $url = $is_sample?mkfileurl($GLOBALS['DB']->Query("SELECT files.id FROM files LEFT JOIN template_files ON template_files.fid=files.id ".                    
                                     "WHERE files.filename='{$t[1][0]}' AND template_files.tid=$template AND template_files.deleted=0", 1)):
                                     "cid:{$t[1][0]}";
        $style=''; $size='';
        if($t[3]) foreach(explode(':', strtolower($t[3][0])) as $param) switch($param) 
        {
        case 'left': $style .= "float:left;"; break;
        case 'right': $style .= "float:right;"; break;
        default: if(preg_match("/^(width|height)=\d+%?$/", $param)) $size .= ' '.$param;
        }
        if($style!='') $style = "style=\"$style\"";
        $tpl = substr_replace($tpl, "<img src='$url' $size $style>", $t[0][1], strlen($t[0][0]));
    }
    return $tpl;
    }

Автор: FireDemon 25.3.2008, 11:49
Проблема в том что preg_match("/{([^:}]+)(:([^}]+))?(.*){\/\\1}/s",$tpl,$m = array()) выдает пустой массив, но в php4 все работало.

Автор: smartov 25.3.2008, 11:57
Функция preg_match вообще массивов не возвращает. Она boolean вертает. 

А если ты про третий параметр, то скажи на милость, зачем там стоит $m = array(). Конечно же ты с такой записью будешь ВСЕГДА получать в $m пустой массив.

Добавлено @ 11:58
Цитата(FireDemon @  25.3.2008,  10:49 Найти цитируемый пост)
но в php4 все работало.

Значит php4 работал неправильно.

Автор: FireDemon 25.3.2008, 12:00
smartov, спасибо большое.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)