使用正则表达式排除标记及其内容

时间:2014-07-28 10:51:22

标签: php regex preg-replace

我正在编写一个项目,其中包含模板引擎和一些新定义的标签,如LOOPIF等......

假设这是PHP应处理并转换为PHP脚本的模板块:

<LOOP products>
    {{name}}
    {{id}}

    <LOOP comments>
        {{name}}
    </LOOP>

    {{quantity}}
</LOOP>

我想转换所有{{variables}}根据循环变量的属性将它们打印出来,但我想为每个循环排除内部LOOP标记。 < / p>

因为第一个LOOP {{name}}标记应为$product->name,第二个LOOP的名称应为$comment->name < / p>

此正则表达式会将所有{{variables}}转换为LOOP的第一个product变量。

$pattern = '/\s*\{\{(\w+)+\}\}\s*/';

以上输出

<LOOP products>
    {{name}} // $product->name
    {{id}} // $product->id

    <LOOP comments>
        {{name}} // $product->name ! <-- this {{variable}} should 
                 // be exculde of first loop converting.
    </LOOP>

    {{quantity}} // $product->quantity
</LOOP>

更新

我也试过这个:

(?!<LOOP[^>]*?>)\{\{(\w+)+\}\}(?![^<]*?</LOOP>)
// this works for 2 level of nested LOOPs.
// when I add another LOOP as third level ...
// ... contents of level2 are changing too, which is not corrent.
// ONLY first level should change.

2 个答案:

答案 0 :(得分:2)

首先应该从文本中创建数据树。之后,您可以应用变量替换。

  1. 搜索循环标记并拆分文档,以便获得如下数据结构:

    • LOOP:产品
      • 文字:{{name}} {{id}}
      • LOOP:评论
        • 文字:{{name}}
      • 文字:{{quantity}}
  2. 浏览所有LOOP数据条目并用正则表达式替换所有TEXT字符串

  3. 通过遍历数据结构重建文本文档

  4. 在增强模板系统时,这将为您提供极大的灵活性。它也更容易维护。

答案 1 :(得分:1)

Dreamlab是正确的:don't try to parse XML/HTML with regex。使用XML / HTML解析器处理数据,并以这种方式排除内部循环。这是一个特别复杂的问题,使用正则表达式来解决这个问题,当您使用适当的工具进行工作时,这会非常容易。在您的情况下,将XML抛出到SimpleXML并遍历树或使用一些XPath。

当正则表达式是你的锤子时,所有东西有时看起来像钉子,但它在很多情况下都是一个非常糟糕的工具 - 对你的问题来说是一个特别糟糕的工具。正则表达式并不是为解决这类问题而建立的,如果你试图这样做,你就会发现痛苦。

旁注:似乎你可能也在试图发明一种新的模板语言。如果是这样,你可能不需要。捆绑MustacheSmartyTwig或其他众多已经存在且经过充分测试和运行的模板引擎。

听起来你可能正在编写某种框架,所以这可能不适用,但根据你的用例,你可以只使用PHP,因为PHP 是一种模板语言:< / p>

<?php for($products as $p): ?>
    <?=$p['name']?>
    <?=$p['id']?>

    <?php for($p['comments'] as $c): ?>
        <?=$c['name']?>
    <?php endforeach ?>

    <?=$p['quantity']?>
<?php endforeach ?>