2011-02-24 42 views
2

我想編寫symple(包含一個preg_replace調用)論壇分析器,我遇到嵌套標籤的問題。PHP PCRE - 正確的嵌套標籤行爲

例如如果有人引用某人的話,我就無法達到正確的行爲。

當具有:

[quote=Tom] 

[quote=Jerry] 
Lorem 
[/quote] 

Ipsum 

[/quote] 

Dolor. 

我想是這樣的:

<blockquote> 
    <p><strong>Tom wrote</strong></p> 
    <blockquote> 
     <p><strong>Jerry wrote:</strong></p> 
     <p>Lorem</p> 
    </blockquote> 

    Ipsum 
</blockquote> 

Dolor. 

我有這樣的代碼:

preg_replace('~\[quote (.+)\](.+)\[/quote\]~is', '<blockquote><p><strong>$1</strong> wrote:</p><p>$2</p></blockquote>', $value); 

這個版本是貪婪。如果我有兩個獨立的塊,則正則表達式會覆蓋第一個[quote]和第二個[/quote]之間的所有文本。

如果我添加了U改性劑,它太ungreedy - 第一[quote]標籤與第一(嵌套和不相關)[/quote]標籤配對。

感謝您的幫助!

+0

您可能需要查看遞歸正則表達式,它可以處理該問題,或者實際使用/創建解析器,而不是僅依賴於正則表達式。 – Orbling 2011-02-24 16:05:04

+2

嗨,giyf:http://stackoverflow.com/questions/2909588/regex-bbcode-perfecting-nested-quote – soju 2011-02-24 16:07:45

回答

1

不要使用正則表達式這一點。使用官方提供的PECL擴展:

示例(從文檔取消):

<?php 
$arrayBBCode=array(
    ''=>   array('type' => BBCODE_TYPE_ROOT, 'childs' => '!i'), 
    'i'=>  array('type' => BBCODE_TYPE_NOARG, 'open_tag' => '<i>', 
        'close_tag' => '</i>', 'childs' => 'b'), 
    'url'=>  array('type' => BBCODE_TYPE_OPTARG, 
        'open_tag' => '<a href="{PARAM}">', 'close_tag' => '</a>', 
        'default_arg' => '{CONTENT}', 
        'childs' => 'b,i'), 
    'img'=>  array('type' => BBCODE_TYPE_NOARG, 
        'open_tag' => '<img src="', 'close_tag' => '" />', 
        'childs' => ''), 
    'b'=>  array('type'=>BBCODE_TYPE_NOARG, 'open_tag' => '<b>', 
        'close_tag' => '</b>'), 
); 

$text = <<<EOF 
[b]Bold Text[/b] 
[i]Italic Text[/i] 
[url]http://www.php.net/[/url] 
[url=http://pecl.php.net/][b]Content Text[/b][/url] 
[img]http://static.php.net/www.php.net/images/php.gif[/img] 
[url=http://www.php.net/] 
[img]http://static.php.net/www.php.net/images/php.gif[/img] 
[/url] 
EOF; 

$BBHandler = bbcode_create($arrayBBCode); 
echo bbcode_parse($BBHandler, $text); 
?> 

The full docs.

0

遞歸正則表達式的一些幫助:

function replace_quotes_callback($matches) { 
    $cite = empty($matches[1]) ? '' : '<p><strong>' . $matches[1] . '</strong> wrote:</p>'; 
    return '<blockquote>' . $cite . '<p>' . replace_quotes($matches[2]) . '</p></blockquote>'; 
} 

function replace_quotes($data) { 
    return preg_replace_callback('~\[quote(?:=([^\]]+))?\]((?:(?R)|.)*?)\[/quote\]~s', 'replace_quotes_callback', $data); 
} 

該模式的匹配最外層的引用塊,回調函數replace_quotes_callback通過遞歸調用來代替內部引號0。