PHP正则表达式递归匹配

时间:2009-09-20 22:55:11

标签: php regex nested

我正在尝试匹配模板文件中的某组标签。但我想要标签 能够嵌套在自己身上。

我的正则表达式如下:(使用/ s)

<!-- START (.*?) -->(.*?)<!-- END \\1 -->

标签示例:

<!-- START yList -->
  y:{yList:NUM} | 
  <!-- START xList -->
    x:{xList:NUM} 
  <!-- END xList -->
  <!-- CARET xList -->
  <br>
<!-- END yList -->
<!-- CARET yList -->

现在匹配结果将是:

匹配0:

组(0)(整场比赛)

<!-- START yList --> 
 y 
 <!-- START xList --> 
   x 
 <!-- END xList --> 
 <!-- CARET xList --> 
 <br> 
<!-- END yList -->

基团(1)

yList

基团(2)

y 
<!-- START xList --> 
  x 
<!-- END xList --> 
<!-- CARET xList --> 
<br>

我希望2匹配而不是1匹配,嵌套标签集不匹配。这有可能与正则表达式,或者我应该保持regexing组(2)结果,直到我没有找到新的匹配?

2 个答案:

答案 0 :(得分:5)

正则表达式不适合解析任意深度的树结构。根据你正在使用的正则表达式的风格,可能会这样做,但不推荐 - 它们很难阅读,也很难调试。

我建议改为编写一个简单的解析器。你所做的是将你的文本分解为一组可能的标记,每个标记都可以用简单的正则表达式来定义,例如:

START_TOKEN = "<!-- START [A-Za-z] -->"
END_TOKEN = ...
HTML_TEXT = ...

迭代你的字符串,只要你匹配这些标记,将它们拉出字符串,然后将它们存储在一个单独的列表中。执行此操作时,请务必保存令牌内的文本(如果有)。

然后,您可以遍历您的令牌列表,并根据令牌类型,您可以创建节点的嵌套树结构,每个节点包含1)原始令牌的文本,以及2)子节点列表。

如果这看起来太复杂,您可能需要查看一些解析器教程。

答案 1 :(得分:0)

你可以这样做:

$parts = preg_split('/(<!-- (?:START|END|CARET) [a-zA-Z][a-zA-Z0-9]* -->)/', $str, -1, PREG_SPLIT_DELIM_CAPTURE);
$tokens = array();
$isTag = isset($tokens[0]) && preg_match('/^<!-- (?:START|END|CARET) [a-zA-Z][a-zA-Z0-9]* -->$/', $tokens[0]);
foreach ($parts as $part) {
    if ($isTag) {
        preg_match('/^<!-- (START|END|CARET) ([a-zA-Z][a-zA-Z0-9]*) -->$/', $token, $match);
        $tokens[] = array($match[1], $match[2]);
    } else {
        if ($token !== '') $tokens[] = $token;
    }
    $isTag = !$isTag;
}
var_dump($tokens);

这将为您提供代码的结构。

相关问题