【问题标题】:preg_replace_callback with Spoilers into Spoilerspreg_replace_callback 与 Spoilers 成 Spoilers
【发布时间】:2014-05-19 17:24:34
【问题描述】:

我写了类似[spoiler=Spoiler Title]text inside the Spoiler[/spoiler] 并使用preg_replace_callback("/\[spoiler=(.*)\](.*)\[\/spoiler\]/Usi", 'BBCode_spoiler', $text); 创建一个真正的剧透,一个或多个剧透的结果是:

<script type="text/javascript">
    function show_0() {
        if(document.getElementById("0").style.display == "inline-block")
            document.getElementById("0").style.display = "none";
        else document.getElementById("0").style.display = "inline-block"; }
</script>
<a href="javascript:show_0();"><i>Show Spiler:</i> <b>Spoiler Title</a></b><br>
<div id="0" style="display: none; min-width: 100px; border-bottom: 1px solid #000000; border-right: 1px solid #000000; background-color: #FFFFFF; color: #000000;">
    Text inside the Spoiler
</div>

我如何使它与扰流板一起工作成为扰流板 喜欢[spoiler=Spoiler Title][spoiler=Second Spoiler]Another Text[/spoiler][/spoiler] 我当前的函数没有剧透返回到剧透中

<script type="text/javascript">
    function show_0() {
        if(document.getElementById("0").style.display == "inline-block")
            document.getElementById("0").style.display = "none";
        else document.getElementById("0").style.display = "inline-block"; }
</script>
<a href="javascript:show_0();"><i>Show Spiler:</i> <b>Spoiler Title</a></b><br>
<div id="0" style="display: none; min-width: 100px; border-bottom: 1px solid #000000; border-right: 1px solid #000000; background-color: #FFFFFF; color: #000000;">
    [spoiler=Second&nbsp;Spoiler]Another Text</div>[/spoiler]

我的回调函数是

<?php
// Spoiler
$counter = 0;
function BBCode_spoiler($hits) {
    global $central_lang;
    global $counter;
    $title = htmlentities(trim($hits[1]));
    $text = htmlentities($hits[2]);
    $return = "<script type=\"text/javascript\">";
    $return .= "function show_".$counter."() {";
    $return .= "if(document.getElementById(\"".$counter."\").style.display == \"inline-block\") document.getElementById(\"".$counter."\").style.display = \"none\";";
    $return .= "else document.getElementById(\"".$counter."\").style.display = \"inline-block\"; }";
    $return .= "</script>";
    $return .= "<a href=\"javascript:show_".$counter."();\"><i>".$central_lang['bbcodes']['spoiler']['text'].":</i> <b>".$title."</a></b><br>";
    $return .= "<div id=\"".$counter."\" style=\"display: none; min-width: 100px; border-bottom: 1px solid #000000; border-right: 1px solid #000000; background-color: #FFFFFF; color: #000000;\">".$text."</div>";
    $counter++;
    return $return; }
?>

我尝试做的输出看起来像这样

<script type="text/javascript">
    function show_0() {
        if(document.getElementById("0").style.display == "inline-block")
            document.getElementById("0").style.display = "none";
        else document.getElementById("0").style.display = "inline-block"; }
</script>
<a href="javascript:show_0();"><i>Show Spoiler:</i> <b>Spoiler Title</a></b><br>
<div id="0" style="display: none; min-width: 100px; border-bottom: 1px solid #000000; border-right: 1px solid #000000; background-color: #FFFFFF; color: #000000;">
    <script type="text/javascript">
        function show_1() {
            if(document.getElementById("1").style.display == "inline-block")
                document.getElementById("1").style.display = "none";
            else document.getElementById("1").style.display = "inline-block"; }
    </script>
    <a href="javascript:show_1();"><i>Show Spoiler:</i> <b>Second Spoiler</a></b><br>
    <div id="1" style="display: none; min-width: 100px; border-bottom: 1px solid #000000; border-right: 1px solid #000000; background-color: #FFFFFF; color: #000000;">
        Another text
    </div>
</div>

希望我的问题有答案,谢谢!

【问题讨论】:

    标签: php regex preg-replace-callback


    【解决方案1】:

    你可以使用preg_replace_callback的count参数来处理从最里面到最外面的替换,直到没有更多的标签可以替换:

    $pattern = '~\[spoiler=([^]]*)]((?>[^[]+|\[(?!/?spoiler\b))*)\[/spoiler]~i';
    
    do {
        $result = preg_replace_callback($pattern, 'BBCode_spoiler', $text, -1, $count);
    } while ($count>0);
    

    我稍微改变了模式以确保匹配是最里面的标签。

    【讨论】:

      【解决方案2】:

      这通常适用于 BBCode:重新运行替换代码,直到它停止更改为止。

      preg_replace_callback 接受一个“count”引用变量,该变量将填充替换的次数。只要这个数字不为零,您就应该重新运行替换(do..while 非常适合)

      它们是否交叉并不重要。假设我们有一个 BBCode 将 [div] 替换为 &lt;div&gt;...

      [div]Blah[div]123[/div]Fish[/div]
      

      更换一次后:

      <div>Blah[div]123</div>Fish[/div]
      

      再次更换后:

      <div>Blah<div>123</div>Fish</div>
      

      因此,即使它们是按交叉顺序处理的,结果也是正确嵌套的。

      【讨论】:

      • 谢谢你,我终于成功了!我将模式更改为/\[spoiler=(.*)\](.*)/Usi,并在我的 preg_replace_callback 函数之后添加了$text = str_replace("[/spoiler]", "&lt;/div&gt;", $text);...我在没有$counter 的情况下完成了它,但它也能正常工作!谢谢
      • Alex 的问题是,如果我输入 [/spoiler] 时没有开始标签会怎样?您网站的结构将崩溃!
      • *如果$counter大于0,它就可以改变[/spoiler];)
      • [spoiler=Test][/spoiler][/spoiler],效果?
      • 会的,但只有一次
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-28
      • 2017-06-02
      • 2016-02-07
      相关资源
      最近更新 更多