在PHP中删除嵌套的bbcode(引号)

时间:2010-08-27 06:32:58

标签: php regex nested bbcode

我正在尝试从公告板中删除嵌套引用,但我遇到了一些问题。

示例输入:

  

[quote author = personX link = topic = 12.msg1910#msg1910 date = 1282745641]

[quote author=PersonY link=topic=12.msg1795#msg1795 date=1282727068]

The message in the original quote

[/quote]
     

引用第一条消息的第二条消息

     

[/报价]

     

[quote author = PersonZ link = topic = 1.msg1#msg1 date = 1282533805]

     

随机第三个引用

     

[/报价]

示例输出

  

[quote author = personX link = topic = 12.msg1910#msg1910 date = 1282745641]

     

第二个引文中的消息

     

[/报价]

     

[quote author = PersonZ link = topic = 1.msg1#msg1 date = 1282533805]

     

随机第三个引用

     

[/报价]

正如您所看到的,嵌入的引用(原始消息)以及引号标记已被删除。

我似乎无法弄明白。

当我尝试

$toRemove = '(\\[)(quote)(.*?)(\\])';
$string = $txt;
$found = 0; echo preg_replace("/($toRemove)/e", '$found++ ? \'\' : \'$1\'', $string);

除去第一个引号标记

之外,它会删除每个引号标记

但是当我将代码扩展为:

$toRemove = '(\\[)(quote)(.*?)(\\])(.*?)(\\[\\/quote\\])';
$string = $txt;
$found = 0; echo preg_replace("/($toRemove)/e", '$found++ ? \'\' : \'$1\'', $string); 

它完全没有做任何事情。

有关于此的任何想法吗?


编辑:

感谢您的帮助,Haggi。

尽管如此,我仍然遇到麻烦。

围绕

的while循环
while ( $input = preg_replace_callback( '~\[quoute.*?\[/quote\]~i', 'replace_callback', $input ) ) {
// replace every occurence
}

导致页面无限循环,当删除时(以及quoute中的额外u),页面不会执行任何操作。

我已确定原因是匹配的

更改为

$input = preg_replace_callback( '/\[quote(.*?)/i', 'replace_callback', $input );

代码确实开始工作,但是当更改为

$input = preg_replace_callback( '/\[quote(.*?)\[\/quote\]/i', 'replace_callback', $input );

它停止再做任何事情。

此外,undo_replace函数存在问题,因为它永远不会找到存储的哈希值,它只会提供有关未完成索引的警告。匹配sha1的正则表达式无法正常工作。

我现在拥有的完整代码:

$cache = array();
$input = $txt;

function replace_callback( $matches ) {
    global $cache;
    $hash = sha1( $matches[0] );
    $cache["hash"] = $matches[0];
    return "REPLACE:$hash";
}



// replace all quotes with placeholders
$input = preg_replace_callback( '/\[quote(.*?)\[quote\]/i', 'replace_callback', $input );

function undo_replace( $matches ) {
    global $cache;
    return $cache[$matches[1]];
}

// restore the outer most quotes
$input = preg_replace_callback( '~REPLACE:[a-f0-9]{40}~i', 'undo_replace', $input );

// remove the references to the inner quotes
$input = preg_replace( '~REPLACE:[a-f0-9]{40}~i', '', $input );

echo $input;

再次感谢任何想法的人:)

2 个答案:

答案 0 :(得分:2)

第一个是唯一一个很容易找到的人:

'$found++ ? \'\' : \'$1\''

当启动$ found未定义并且计算结果为false时返回$ 1。然后$ found增加到1(undefined + 1 = 1),因此它大于零,每次调用它时,它会进一步递增。因为所有与零不同的东西在之后被评估为真,所以你总是得到''返回。

你想做的是这样的事情

$cache = array();

function replace_callback( $matches ) {
    global $cache;
    $hash = sha1sum( $matches[0] );
    $cache[$hash] = $matches[0];
    return "REPLACE:$hash";
}

// replace all quotes with placeholders
$count = 0;
do {
    $input = preg_replace_callback( '~\[quoute.*?\[/quote\]~i', 'replace_callback', $input, -1, $count );
    // replace every occurence
} while ($count > 0);

function undo_replace( $matches ) {
    global $cache;
    return $cache[$matches[1]];
}

// restore the outer most quotes
$input = preg_replace_callback( '~REPLACE:[a-f0-9]{40}~i', 'undo_replace', $input );

// remove the references to the inner quotes
$input = preg_replace( '~REPLACE:[a-f0-9]{40}~i', '', $input );

此代码未经测试,因为我手头没有PHP来测试它。如果您有任何错误无法修复,请在此处发布,我会修复它们。

干杯,
haggi

答案 1 :(得分:0)

我用preg_replace为嵌套引号搜索了几个解决方案,但没有人工作。所以我根据我的要求尝试了我的小版本。

$position = strrpos($string, '[/quote:');  // this will get the position of last quote
$text = substr(strip_tags($string),$position+17); // this will get the data after the last quote used. 

希望这会对某人有所帮助。