【问题标题】:Removing nested bbcode (quotes) in PHP [duplicate]删除 PHP 中的嵌套 bbcode(引号)[重复]
【发布时间】:2020-04-25 18:33:26
【问题描述】:

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

输入示例:

[引用作者=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]

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

随机的第三个引用

[/quote]

示例输出

[引用作者=personX link=topic=12.msg1910#msg1910 date=1282745641]

第二句中的信息

[/quote]

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

随机的第三个引用

[/quote]

如您所见,嵌套的引用(原始消息)连同引用标记已被删除。

我好像想不通。

当我尝试时

$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); 

它完全停止做任何事情。

对此有什么想法吗?


编辑:

感谢您的帮助,哈吉。

尽管如此,我还是会遇到麻烦。

while循环

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

导致页面无限循环,当被移除时(连同额外的 u 在 quoute),页面不做任何事情。

我已经确定原因是匹配

什么时候改成

$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;

再次感谢大家的任何想法:)

【问题讨论】:

  • 请替换 $cache["hash"] = $matches[0];通过 $cache[$hash] = $matches[0];
  • 修复了循环中的错误。请在我编辑的帖子中尝试新版本

标签: php regex nested bbcode


【解决方案1】:

第一个是唯一留下来的很容易发现:

'$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,但感谢您的帮助。我已经用我的发现编辑了原始帖子。
【解决方案2】:

我已经搜索了几个使用 preg_replace 嵌套引号的解决方案,但没有一个有效。所以我根据我的要求尝试了我的littel版本。

$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. 

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-02-06
    • 1970-01-01
    • 2018-05-30
    • 2013-09-23
    • 2017-09-19
    • 2014-07-18
    • 1970-01-01
    相关资源
    最近更新 更多