正则表达式以匹配打开和关闭的自定义标签

时间:2019-02-19 04:31:23

标签: php regex templates tags

我正在设计一个自定义模板解析器,并且想要编译模板 内容通过{php xxx}模板语法转换为php代码。

我尝试使用

preg_replace('/{php\s+([^}]+)*}/', '<?php $1?>', '{php echo 'a' }');可以由{php echo 'a' }<?php echo 'a' ?>

用一行显示

然后使用多行更改模式支持

$content = "
{php print_r([
    'foo' => 'bar',
])}
";
echo preg_replace('/{php\s+([^}]+)*}/', '<?php $1?>', $content);

现在的问题是如何以{php xxx}模板语法支持php函数。

源模板内容:

{php echo yii\bootstrap\Nav::widget([
   'options' => ['class' => 'navbar-nav'],
    'items' => array_walk($menu, function($data) {
       return yii\helpers\ArrayHelper::remove($data, 'items');
    }),
]); }

目标php代码

<?php echo yii\bootstrap\Nav::widget([
   'options' => ['class' => 'navbar-nav'],
    'items' => array_walk($menu, function($data) {
       return yii\helpers\ArrayHelper::remove($data, 'items');
    }),
]); ?>

1 个答案:

答案 0 :(得分:0)

正如我在评论中已经提到的,正则表达式是解析结构化代码的错误工具。

但是,只要您可以确保括号总是成对出现且未转义,则可以使用递归正则表达式:

<?php
declare (strict_types=1);

$subject = <<<'EOS'
<div>{php echo yii\bootstrap\Nav::widget([
   'options' => ['class' => 'navbar-nav'],
    'items' => array_walk($menu, function($data)
    {
      if(true)
      { 
        $x = "{}sdf{ {{}{}}{} }";
      }
      return yii\helpers\ArrayHelper::remove($data, 'items');
    }),
]); }</div>

<div>{php echo yii\bootstrap\Nav::widget([
   'options' => ['class' => 'navbar-nav'],
    'items' => array_walk($menu, function($data)
    {
      if(true)
      { 
        $x = "{}sdf{ {{}{}}{} }";
      }
      return yii\helpers\ArrayHelper::remove($data, 'items');
    }),
]); }</div>
EOS;

var_dump(preg_replace( '~{php(\s([^{}]|{([^{}]*(?2))*})*)}~suU', '<?php\1?>', $subject));

在线测试:https://regex101.com/r/hGqVeq/2