这个正则我在正则表达式测试器里测试通过,但拿到PHP中就不可以使用~求解这个如何写才能在PHP中实现?
$patterns = '/'.$begintag.'([\s\S]*?)(((?<Open>'.$begintag.')([\s\S]*?))+((?<-Open>'.$endtag.')([\s\S]*?))+)*(?(Open)(?!))'.$endtag.'/';
以上是PHP的语句,下面是$begintag和$endtag变量被赋值后的正则规则示例:
\{Cms:cates(\s([^\}]*)|)\}([\s\S]*?)(((?<Open>\{Cms:cates(\s([^\}]*)|)\})([\s\S]*?))+((?<-Open>\{\/Cms:cates(\s*?)\})([\s\S]*?))+)*(?(Open)(?!))\{\/Cms:cates(\s*?)\}难道PHP不支持正则平衡组,正则堆栈的用法吗?
PHP正则表达式平衡组堆栈多层嵌套

解决方案 »

  1.   

    示例<?php
    $s =<<< TXT
    其他文本其他文本 <div>仅单层 </div> </div>(注意:后面多一个 </div>)
    其他文本其他文本其他文本
    <div>外层
         <div>中层
             <div>内层 </div>
         </div>
    </div>
    # 这是另一种情况
    # start 闭合错误
    <div>外层
         <div>中层
             <div>内层 </div>
         </div>
    </font>
    # end 闭合错误
    其他文本 <font>外层 <span>里层 </span> </font>其他文本其他文本……
    TXT;
    $p = "/<([a-z]+)[^>]*>([^<>]|(?R))*<\/\\1>/is";preg_match_all($p,$s,$m);print_r($m[0]);Array
    (
        [0] => <div>仅单层 </div>
        [1] => <div>外层
         <div>中层
             <div>内层 </div>
         </div>
    </div>
        [2] => <div>中层
             <div>内层 </div>
         </div>
        [3] => <font>外层 <span>里层 </span> </font>
    )
      

  2.   


    比如我要用Cms:navlist来匹配下面一段,按你发的规则改过,然后就不好用:
    <ul>
    {Cms:navlist }
    <dl class="fl {if condition='$navlist.id eq 1'}on{elseif condition='$navlist.id eq 4' /}light{/if}">
    <dt><a href="{$navlist.url}">{$navlist.title}</a></dt>
    {Cms:navlist pid="$navlist['id']" item="navlist1" key='key1' elem='dd'}
    <div><a href="{$navlist1.url}">{$navlist1.title}</a></div>
    {/Cms:navlist}
    </dl>
    {/Cms:navlist}
    </ul>
      

  3.   

    你想说的是这个么?<?php
    $str =<<<'EOF'
    <ul>
        {Cms:navlist }
            <dl class="fl {if condition='$navlist.id eq 1'}on{elseif condition='$navlist.id eq 4' /}light{/if}">
                <dt><a href="{$navlist.url}">{$navlist.title}</a></dt>
                {Cms:navlist pid="$navlist['id']" item="navlist1" key='key1' elem='dd'}
                    <div><a href="{$navlist1.url}">{$navlist1.title}</a></div>
                {/Cms:navlist}
            </dl>
        {/Cms:navlist}
    </ul>
    EOF;preg_match('#\{(Cms:[a-z]+)[^\}]*\}(([^\{\}]|{(?!=Cms)[^\}]*\}|(?R))*)\{\/\\1\}#i',$str,$val);
    print_r($val);
      

  4.   


    就是这个,就是这个,不过有点点问题:我这个用于解析模板标签,在{Cms:navlist}{/Cms:navlist}里面有可能嵌套其他{Cms:xxx}{/Cms:xxx}类型的标签,也有可能是{if}{/if}或者{foreach}{/foreach}或者变量{$aaa.bbb}或者其他以{}包裹起来的东西,但只要不是{Cms:navlist}就可以……
    这样的话是不是上面语句的(?!=Cms)要改成(?!=Cms:navlist)?
      

  5.   


    就是这个,就是这个,不过有点点问题:我这个用于解析模板标签,在{Cms:navlist}{/Cms:navlist}里面有可能嵌套其他{Cms:xxx}{/Cms:xxx}类型的标签,也有可能是{if}{/if}或者{foreach}{/foreach}或者变量{$aaa.bbb}或者其他以{}包裹起来的东西,但只要不是{Cms:navlist}就可以……
    这样的话是不是上面语句的(?!=Cms)要改成(?!=Cms:navlist)?
    我对(?!=)这个语法一只不是很明白
      

  6.   

    还有些问题,用这段正则对以下代码进行解析匹配时会不正确匹配:
    <ul>
        {Cms:navlist }
            <dl class="fl {if condition='$navlist.id eq 1'}on{elseif condition='$navlist.id eq 4' /}light{/if}">
                <dt><a href="{$navlist.url}">{$navlist.title}</a></dt>
                {Cms:navlist pid="$navlist['id']" item="navlist1" key='key1' elem='dd'}
                    <div><a href="{$navlist1.url}">{$navlist1.title}</a></div>
                {/Cms:navlist}
            </dl>{/Cms:navlist}
        {/Cms:navlist}<!--这里多一组关闭标签-->
    </ul>PHP真的就没有正则堆栈的支持吗?我感觉这种递归的正则还是有很大的缺陷的
      

  7.   


    版主大大说的太对了,正则也不是万能,正则主要是处理模式化的东西,而如果非模式化的东西最好还是有代码来完成,否则就太费力了。
    例如你说的那个情况,完全可以多用几次查找就可以实现,例如真正用代码实现一个堆栈的方式来处理。
    话是这样说不错~但我实在是不明白为什么PHP正则为什么不支持其他语言正则的组平衡语法~
    是可以用代码来完成,但我觉得PHP是一个解释性语言,用另外的语句来实现远不如直接用内置的函数来做性能高。如果是C代码那种编译型的语言,需要的功能不多的情况下倒是完全没必要引用外部扩展库,自己写几行代码性能上应该会更高一些~
    如果用PHP代码来另外完成这个标签查找匹配的操作,会另外多执行好多好多次循环、正则等操作,纠结中~
      

  8.   

    我猜LZ是想写个CMS...个人也试过,逐层剥离
      

  9.   


    是要逐层剥离,但现在层次的判断有些问题,只有层次判断OK以后才能继续下一步的逐层分析替换内容~我估计PHP的正则也许真的实现不了了,看来只能损失性能来写专门的语法分析代码了~
      

  10.   


    是要逐层剥离,但现在层次的判断有些问题,只有层次判断OK以后才能继续下一步的逐层分析替换内容~我估计PHP的正则也许真的实现不了了,看来只能损失性能来写专门的语法分析代码了~
    我也是多次遇到这个问题了,一个是想写cms,另外一个是html标签选择器,不过都没能实现。