繁体   English   中英

PHP-我的Regex需要一些帮助

[英]PHP - I need some help with my Regex

我已经在PHP中创建了一个简单的模板“引擎”,以将PHP生成的数据替换为HTML页面。 运作方式如下:

在我的主模板文件中,我有如下变量:

<title><!-- %{title}% --></title>

然后,我将数据分配给这些变量以供主页加载

$assign = array (
  'title' => 'my website - '
);

然后,我将为内容页面加载单独的模板块。 上面的内容实际上只是处理页眉和页脚。 在这些“内容模板文件”之一中,我具有如下变量:

<!-- %{title=content page}% -->

执行此操作后,将编辑主模板数据以包含内容页面变量,从而导致:

<title>my website - content page</title>

它使用以下代码执行此操作:

if (preg_match('/<!-- %{title=\s*(.*?)}% -->/s', $string, $matches)) {
   // Find variable names in the form of %{varName=new data to append}%
   // If found, append that new data to the exisiting data
   $string       = preg_replace('/<!-- %{title=\s*(.*?)}% -->/s', null, $string);
   $varData[$i] .= $matches[1];
}

这基本上删除了模板变量,然后将变量数据分配给现有变量。 现在,一切正常。 我遇到的问题是嵌套模板变量。 如果我做类似的事情:

<!-- %{title=content page (author: <!-- %{name}% -->) -->

该模式有时会弄乱每个变量的开始和结束标签。

如何解决我的正则表达式以防止这种情况?

谢谢。

答案是您不使用正则表达式执行此操作。 正则表达式是一种正则语言。 当您开始嵌套事物时,它不再是常规语言。 至少是无上下文语言(“ CFL”)。 CFL仅可以使用堆栈进行处理(假设它们是明确的)。

具体而言,可以使用有限状态机(“ FSM”)来表示常规语言。 CFL需要下推式自动机(“ PDA”)。

差异的一个示例是HTML中的嵌套标签:

<div>
  <div>inner</div>
</div>

我的建议是不要编写自己的模板语言。 已经做完了。 多次。 使用Smarty或Zend,Kohana等中的任何东西。 如果您自己编写,请正确执行。 解析它。

为什么要滚动自己的模板引擎? 如果您需要这种复杂性,那么已经有很多地方提出了解决方案。 您应该只插入Smarty或类似的东西。

如果您要问的是我想问的问题,那实际上是不可能的。 如果我正确阅读了您的问题,则希望将任意嵌套的<!-- ... --> -...- <!-- ... -->序列与内部的特定内容进行匹配。 不幸的是,正则表达式只能匹配某些类别的字符串。 任何正则表达式都只能匹配正规语言 一种常见的众所周知的语言是平衡括号内语言(也称为Dyck语言) ,这正是您要匹配的语言。 为了匹配任意嵌套的注释字符串,您需要一个功能更强大的工具。 我相当确定有预先存在的PHP模板引擎; 您可能会研究其中之一。

要解决您的问题,您应该

  • preg_match()替换preg_match_all() ;
  • 找到模式,并从最后一个替换为第一个;
  • 使用更严格的模式,例如'/<!-- %{title=\\s*([^}]*?)}% -->/s'

我过去做过类似的事情,并且遇到了与您相同的嵌套问题。 在您的情况下,我会重复搜索文本以查找匹配项(而不是搜索一次并遍历匹配项),并通过搜索不包含结束字符串的任何内容来提取所需的字符串。

在您的情况下,它可能看起来像这样:

/(<!--([^(-->)]*?)-->)/

像这样的正则表达式是一个噩梦般的解释,但是([^(-->)]*)基本上会找到任何不包含结束标记的字符串(我们称之为AAA )。 它将位于一个匹配组内部,该组本身就是您的模板标签(<!--AAA-->)

我坚信这种模板化方法是做事的错误方法,但是我从来不知道做得更好。 在ASP和ColdFusion中,总是让我感到困扰的是,您不得不将脚本标记嵌套在HTML中,当我自己开始这样做时,我认为这是个人的失败。

我现在使用的大多数正则表达式都使用JavaScript,因此我可能会缺少PHP通过Perl提供的一些很棒的细微差别。 如果有人能写得更清楚我会很高兴。

尽管我没有使用正则表达式,但过去我也遇到过这个问题。

相反,如果您使用strrpos (PHP5 +)从右到左搜索语法中的开始标记<!-- %{ ,然后向前搜索下一个关闭标记的第一个匹配项,然后首先替换该块,最终将首先替换最里面的嵌套变量。 这应该可以解决您的问题。

您也可以用另一种方法进行操作,找到第一次出现的结束标记,然后向后工作以找到其对应的开始标记。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM