递归正则表达式匹配smarty if else语句

时间:2013-11-25 15:25:02

标签: php regex recursion smarty

我想匹配smarty模板中的if else语句。并插入我自己的标签。在我的示例中<OPEN></CLOSE>

这是我的代码:

$value =
<<<SMARTY
{if}
    text1
    {if}
        text2
    {/if}
    text3
{/if}


{if}
    text1
{else}
    text2
{/if}


{if}
    text1
    {if}
        text2
    {else}
        text3
    {/if}
    text
{/if}
SMARTY;

echo filter($value);
function filter($value)
{
    $pattern =
        '(\{(?:if|else).*?\})'.  // open
        '((?:'.

        '[^{]'.
        '|\{(?!/?if|else)'.
        '|(?R)'.

        ')+)'.
        '(\{(?:\/if|else)\})';   // close

    return preg_replace_callback('#'.$pattern.'#', 'filter_callback', $value);
}
function filter_callback($matches)
{
    $m2 = $matches;
    $m2[0] = preg_replace(array('/[\n\r]/','/ +/','/^ /'),array('',' ',''), $m2[0]);
    $m2[2] = preg_replace(array('/[\n\r]/','/ +/','/^ /'),array('',' ',''), $m2[2]);
    print_r($m2);

    return $matches[1].'<OPEN>'.filter($matches[2]).'</CLOSE>'.$matches[3];
}

但它正常工作。

例如,我希望得到以下输出:

{if}<OPEN>
    text1
</CLOSE>{else}<OPEN>
    text2
</CLOSE>{/if}

{if}<OPEN>
    text1
    {if}<OPEN>
        text2
    </CLOSE>{else}<OPEN>
        text3
    </CLOSE>{/if}
    text
</CLOSE>{/if}

如果有人有想法?

2 个答案:

答案 0 :(得分:1)

此任务不需要递归正则表达式。 PHP中的递归正则表达式的问题在于,您无法轻松访问不同递归级别的捕获。对于替换任务,你可以忘记它。

另一种解决方案:

$searches = array('{if}', '{else}', '{/if}');
$reps = array('{if}<OPEN>', '</CLOSE>{else}<OPEN>', '</CLOSE>{/if}');

$result = str_replace($searches, $reps, $value); // probably the faster way

$patterns = array('~{if}~', '~{else}~', '~{/if}~');
$reps = array('$0<OPEN>', '</CLOSE>$0<OPEN>', '</CLOSE>$0');

$result = preg_replace($patterns, $reps, $value);

print_r($result);

注意:您可以使用以下方法避免一次传递:

$patterns = array('~(?<={if}|{else})~', '~(?={(?:/if|else)})~');
$reps = array('<OPEN>', '<CLOSE>');

编辑:如果你想提取params并将它们作为一种标签属性重用,你可以使用preg_replace方式(不需要使用preg_replace_callback)来实现:

$patterns = array('~{if(?:( )[^(}]+\(([^)]+)\))?}~', '~{else}~', '~{/if}~');
$reps = array('$0<OPEN$1$2>', '<CLOSE>$0<OPEN>', '<CLOSE>$0');

$result = preg_replace($patterns, $reps, $value);

注意:描述参数的子模式[^)]+可以替换为(?s)(?>[^)\']++|\'(?>[^\'\\]++|\\{2}|\\.)*\')+,以允许用单引号括起参数内部的括号。

答案 1 :(得分:0)

以下是匹配特殊if语句的具体示例:

$value =
<<<SMARTY
{if}
    text1
    {if \$user->isAllowed(null,'favourites','read')}
        text2
    {/if}
    text3
{/if}


{if \$user->isAllowed(null,'favourites','read')}
    text1
{else}
    text2
{/if}


{if \$user->isAllowed(null,'favourites','read')}
    text1
    {if}
        text2
    {else}
        text3
    {/if}
    text
{/if}
SMARTY;

echo filter($value);
function filter($value)
{
    $pattern =
        '(\{(?:if|else).*?\})'.  // open
        '((?:'.

        '[^{]'.
        '|\{(?!/?if|else)'.
        '|(?R)'.

        ')+)'.
        '(\{(?:\/if|else)\})';   // close

    return preg_replace_callback('#'.$pattern.'#', 'filter_callback', $value);
}
function filter_callback($matches)
{
    if(preg_match('#\{if.*?\$user\-\>isAllowed\((.*?)\)[^\}]*?\}#', $matches[1], $params)) {
        return $matches[1].'<OPEN '.$params[1].'>'.filter($matches[2]).'</CLOSE>'.$matches[3];
    }

    return $matches[1].filter($matches[2]).$matches[3];
}