【问题标题】:RegEx to extract block from twig template [duplicate]正则表达式从树枝模板中提取块[重复]
【发布时间】:2020-07-28 02:05:32
【问题描述】:

在 PHP 中,我想提取树枝块中包含的文本,并认为正则表达式是最有效的。

假设我有一个包含以下内容的文件“index.twig”:

{% block content %}
Content of the page...
{% endblock %}

这段代码运行良好:

$input = file_get_contents("index.twig"); 
preg_match_all('/\{%\s*block\s*content\s*\%}([^\%}]*)\{%\s*endblock\s*\%}/', $input, $output);

$output 将包含预期的结果。

但是,如果输入文件是这样的:

{% block content %}
{{ a_tag }}
Content of the page...
{% endblock %}

在这种情况下,结束的 }} 会破坏正则表达式并且 $output 是空的。

有正确正则表达式的线索吗?

提取块内容的另一种解决方案?

我想得到:

{{ a_tag }}
Content of the page...

【问题讨论】:

  • 为什么要这样做?
  • @DarkBee 我正在为个人项目和教学构建一个非常轻量级的框架
  • 提取树枝模板对我来说看起来很奇怪。无论如何,只是/{% block content %}(.+){% endblock %}/s 所见here
  • 喜欢这个? ^{%.*%}\R((?:(?!{%.*?%}$).*\R)*){%.*%}$regex101.com/r/LtUCiy/1
  • 或使用{%\h*block\h*content\h*%}\R((?:(?!{%\h*endblock\h*%}).*\R)*){%\h*endblock\h*%} regex101.com/r/jFKi84/1

标签: php regex twig


【解决方案1】:

使用[^\%}]* 表示您匹配除使用negated character class 列出的字符之外的任何字符,在本例中为%(您不必转义)和}

使用这种方法,您无法在块之间匹配{{ a_tag }}


获取值的一种方法是匹配块的起始代码,直到第一次出现结束块。在两者之间匹配所有不以 endblock 模式开头的行。

您可以使用\h 来匹配水平空白字符并使用\R 来匹配任何Unicode 换行符序列,而不是使用\s

{%\h*block\h*content\h*%}\R((?:(?!{%\h*endblock\h*%}).*\R)*){%\h*endblock\h*%}

模式将匹配:

  • {%\h*block\h*content\h*%}\R匹配块内容部分和换行符
  • ( 捕获第 1 组
    • (?:(?!{%\h*endblock\h*%}).*\R)* 如果该行不以 endblock 模式开头,则匹配整行和换行符
  • )关闭第一组
  • {%\h*endblock\h*%}匹配端块部分

Regex demo

【讨论】:

    【解决方案2】:

    您可以简单地将与 twig 标签匹配的所有内容替换为空字符串。这是一个例子:

    <?php
    $x = <<<EOT
    {% block content %}
      {{ a_tag }}
      Content of the page...
    {% endblock %}
    EOT;
    
    $x = preg_replace(['/\{%[^\{\}]*%\}\n*/m', '/\{\{[^\{\}]*\}\}\n*/m'], '', $x);
    $y = preg_replace('/\{%[^\{\}]*%\}\n*/m', '', $x);
    print $x;
    print PHP_EOL;
    print $y;
    

    【讨论】:

    • 差不多了!现在有些东西回来了,但没有 twig var。事情是我想在输出中保留 {{ a_tag}}
    • 这不是您最初提出的问题。这仍然是可能的。只需从数组中删除第二个模式。我已经编辑了答案以表明这一点。
    • m 模式修饰符没有用,因为模式中没有 ^$ 元字符。你也在你的模式中做了太多不必要的转义。仅检查\n 将意味着您的解决方案不会支持不同的操作系统(例如使用\r 的操作系统)。请只发布您理解的正则表达式模式,以免误导研究人员。
    【解决方案3】:

    这是我从 cmets 使用的解决方案:

    {%\h*block\h*content\h*%}\R((?:(?!{%\h*endblock\h*%}).*\R)*){%\h*endblock\h*%}
    

    这里有 2 个有用的链接来设置正则表达式模式:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-27
      • 2015-09-27
      • 2020-07-13
      • 2016-08-28
      相关资源
      最近更新 更多