【问题标题】:Regular Expression to match open and closed custom tags正则表达式匹配打开和关闭的自定义标签
【发布时间】:2019-02-19 04:31:22
【问题描述】:

我正在设计一个自定义模板解析器,并且想要编译模板 通过 {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');
    }),
]); ?>

【问题讨论】:

  • 您需要 {php some_text } 的正则表达式?\
  • 考虑 {php echo "text with {$braces['key']}";} 正则表达式是解析复杂结构的错误工具。
  • 最后一个} 总是关闭?如果是这样regex101.com/r/0ukTba/1 我认为可以。如果不是,您需要提供更多示例和更详细的说明。
  • 它甚至可能发生类似{php $end='}'; $start = '{'; echo "$start something $end";} 的情况。然后使用递归表达式嵌套大括号的概念也会被打破。您需要考虑所有情况,例如字符串(单/双 qouted、heredoc、nowdoc...)以及可能出现右大括号的其他情况。
  • 您是设计自己的模板语言还是依赖给定的模板语言?

标签: php regex templates tags


【解决方案1】:

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

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

<?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

【讨论】:

  • 这对我有用。非常感谢您的描述和示例。
猜你喜欢
  • 2018-06-10
  • 1970-01-01
  • 1970-01-01
  • 2013-04-16
  • 2011-09-16
  • 2014-11-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多