用于替换BBCode引号的PHP方法

时间:2013-01-15 14:58:09

标签: php regex bbcode

我需要使用PHP替换phpBB3论坛中的BBCode引号。引用的帖子如下所示:

[quote="John Doe":2sxn61wz][quote="Bob":2sxn61wz]Some text from Bob[/quote:2sxn61wz]Some text from John Doe[/quote:2sxn61wz]Some more text

我想解析这个字符串,最后得到一个像:

这样的数组
Array (

    [0] => Array (

        [0] => 'John Doe' 
        [1] => 'Some text from John Doe'
    )

    [1] => Array (

        [0] => 'Bob' 
        [1] => 'Some text from Bob'
    )
)

递归查找这些引用块及其内容的最佳方法是什么?提前感谢您提供任何帮助!

正如评论中所述:

$str = '[quote="John Doe":2sxn61wz][quote="Bob":2sxn61wz]Some text from Bob[/quote:2sxn61wz]Some text from John Doe[/quote:2sxn61wz]Some more text';
$uid = '2sxn61wz';

print_r(quoteParser($str, $uid));

function quoteParser($str, $uid) {

    $pattern = "#\[quote(?:="(.*?)")?:$uid\]((?!\[quote(?:=".*?")?:$uid\]).)?#ise";

    echo "Unparsed string: " . $str . "<br /><br />";
    echo "Pattern: " . $pattern . "<br /><br />";

    preg_match_all($pattern, $str, $matches);

    return $matches;
}

输出:

Array ( [0] => Array ( [0] => [quote="John Doe":2sxn61wz] [1] => [quote="Bob":2sxn61wz]S ) [1] => Array ( [0] => John Doe [1] => Bob ) [2] => Array ( [0] => [1] => S ) ) 

这完全是我需要的,但我没有得到引用的文字。只有用户名。有帮助吗?谢谢到目前为止。

3 个答案:

答案 0 :(得分:2)

显然你想要的是将你的BBCode输出变成HTML。如果您愿意,可以查看bbcode_create()功能。否则,不同的递归 - 格式化你的文本 - 是一个更好的选择,我相信。

<style type="text/css">

    body {
        font-size:.9em;
        font-family:Arial, Helvetica, sans-serif;
    }

    .post {
        margin:1em;
        padding:1em;
        font-size:1em;
        border:1px solid #999;
    }
    .post > .text {margin:1em .4em}
    .post > div:first-child {margin-top:0}
    .post > div:last-child {margin-bottom:0}

    .post > .quote {border-color:#CCC}
    .quote {
        margin:1em 2em;
        background-color:#F9F9F9;
        border:1px solid #AAA;
        font-style:italic;
    }
    .quote .text {margin:.7em 1em}
    .quote .author {
        color:#039;
        font-size:.8em;
        background-color:#E0E0E0;
        padding:.5em .8em;
        margin:.5em;
    }
    .author a {
        font-weight:bold;
        text-decoration:none;
        color:inherit;
    }
    .author a:hover {text-decoration:underline;}

</style>

function str2html($str,$className='post') {
    $patPost =
    '~(
        \[quote=&quot;(?:(?!&quot;).)+&quot;:(\w+)(?:\])
            (?:
                (?(?=\[quote=&quot;(?:(?!&quot;).+)&quot;:\w+\])
                    (?R)
                    |
                    (?(?!\[/quote:\2\]).)
                )*
            )
        \[/quote:\2\]
    )~xis';
    // note that these 2 are not identical
    $patQuote =
    '~
        (\[quote=&quot;((?:(?!&quot;).)+)&quot;:(\w+)(?:\]))
            (
                (?(?=\[quote=&quot;(?:(?!&quot;).+)&quot;:\w+\])
                    (?R)
                    |
                    (?(?!\[/quote:\3\]).)
                )*
            )
        (\[/quote:\3\])
    ~xis';

    $arr = preg_split($patPost,$str,-1,PREG_SPLIT_DELIM_CAPTURE);
    foreach ($arr as &$value) $value = trim($value);
    unset($value);
    //echo '<h2>split post</h2>'; print_r($arr);

    $res = empty($className) ? '' : "<div class=\"{$className}\">";
    for ($i = 0; $i < count($arr); $i += 3) {
        if (!empty($arr[$i]))
            $res .= '<div class="text">' . $arr[$i] . '</div>';
        if (!empty($arr[$i+1]))
            $res .= preg_replace_callback($patQuote,'replaceQuote',$arr[$i+1]);
    }
    $res .= empty($className) ? '' : '</div>';
    return $res;
}
function replaceQuote($m) {
    //echo '<h2>replacing quotes</h2>'; print_r($m);
    $res = '<div class="quote">';
    $res .= '<div class="author">';
    $res .= '<a href="">' . $m[2] . '</a> wrote:';
    $res .= '</div>';
    $res .= str2html($m[4],'');
    $res .= '</div>';
    return $res;
}

您可以通过echo str2html('some string here')拨打此电话。你明白了。

答案 1 :(得分:1)

这是一个递归版本。它匹配字符串中的所有引号。我就是这样做的。如果整个目的是在html中更好地显示每个代码,那么我将改为使用正确的Regex模式修改内容而不是匹配它们。

$str =  '[quote=&quot;John Doe&quot;:2sxn61wz]' .
        '[quote=&quot;Bob&quot;:2sxn61wz]' .
        'Some text from Bob[/quote:2sxn61wz]' .
        'Some text from John Doe[/quote:2sxn61wz]' . 
        'Some more text';
$str .= '[quote=&quot;MrUpsidown&quot;:2sxn61wz]Some other quote[/quote:2sxn61wz]';
//$str .= '[quote=&quot;MrUpsidown&quot;:2sxn61wz]Yet another one[/quote:2sxn61wz]';

$pat =
'~
    \[quote=&quot;((?:(?!&quot;).)+)&quot;:(\w+)(?:\])
        (
            (?(?=\[quote=&quot;(?:(?!&quot;).+)&quot;:\w+\])
                (?R)
                |
                (?(?!\[/quote:\2\]).)
            )*
        )
    \[/quote:\2\]
~xis';

preg_match_all($pat,$str,$matches);
echo '<h2>Matches:</h2>'; print_r($matches);

$quotes = array();

function replaceQuote($m) {
    global $curArr; global $pat;
    $curArr[] = array(
        'name'  => $m[1],
        'quote' => preg_replace_callback(
            $pat,'replaceQuote',$m[3]
        )
    );
    return preg_replace($pat,'',$m[0]);
}

if (!empty($matches[0])) {
    foreach ($matches[0] as $k => $v) {
        $quotes[] = array(
            array(
                'name'  => $matches[1][$k],
                'quote' => $matches[3][$k]
            )
        );
        $curArr = &$quotes[count($quotes)-1];
        $curArr[0]['quote'] = preg_replace_callback(
            $pat,'replaceQuote',$curArr[0]['quote']
        );
    }
    unset($curArr);
}

echo '<h2>Result:</h2>'; print_r($quotes);

这是输出。

  

匹配

  Array
        (
            [0] => Array
                (
                    [0] => [quote="John Doe":2sxn61wz][quote="Bob":2sxn61wz]Some text from Bob[/quote:2sxn61wz]Some text from John Doe[/quote:2sxn61wz]
                    [1] => [quote="MrUpsidown":2sxn61wz]Some other quote[/quote:2sxn61wz]
                )

            [1] => Array
                (
                    [0] => John Doe
                    [1] => MrUpsidown
                )

            [2] => Array
                (
                    [0] => 2sxn61wz
                    [1] => 2sxn61wz
                )

            [3] => Array
                (
                    [0] => [quote="Bob":2sxn61wz]Some text from Bob[/quote:2sxn61wz]Some text from John Doe
                    [1] => Some other quote
                )

        )
     

结果:

  Array
    (
        [0] => Array
            (
                [0] => Array
                    (
                        [name] => John Doe
                        [quote] => Some text from John Doe
                    )

                [1] => Array
                    (
                        [name] => Bob
                        [quote] => Some text from Bob
                    )

            )

        [1] => Array
            (
                [0] => Array
                    (
                        [name] => MrUpsidown
                        [quote] => Some other quote
                    )

            )

    )

答案 2 :(得分:0)

尝试这样的事情:

$str = '[quote="John Doe":2sxn61wz][quote="Bob":2sxn61wz]Some text from Bob[/quote:2sxn61wz]Some text from John Doe[/quote:2sxn61wz]Some more text';

$quotes=array();

$quotes[]=quoteParser($str,$quotes);
print_r($quotes);

function quoteParser($str,&$quotes) {

    $pattern = "/\[quote(?:=&quot;(.*?)&quot;)?:.{8}?\](.*)\[\/quote:2sxn61wz\](.*)/ise";

    echo "Unparsed string: " . $str . "&lt;br /&gt;&lt;br /&gt;";
        echo "Pattern: " . $pattern . "&lt;br /&gt;&lt;br /&gt;";
    preg_match_all($pattern, $str, $matches);
        if(empty($matches[0][0]))
        return false;

    $var=quoteParser($matches[2][0],$quotes);
        $quotes[]=array($matches[1][0],$var?$var:$matches[2][0]);
    return $matches[3][0];
    }

输出:

数组([0] =&gt;数组([0] =&gt; Bob [1] =&gt;来自Bob的一些文字)[1] =&gt;数组([0] =&gt; John Doe [1] =&gt;来自John Doe的一些文字)[2] =&gt;更多文字)