PHP正则表达式,preg_replace_callback,在1个字符串

时间:2017-05-12 19:27:08

标签: php regex preg-replace

我正在玩这个非常基础的课程,以了解有关正则表达式的更多信息。我想要实现的是从testview文件中获取内容,在{{EACH slides}}和{{#EACH}}之间准确抓取字符串。现在在类中出现的正则表达式就是这样,加上开始标记中的变量名。然后我想使用该字符串将其与正确的变量一起循环并将其放回原位。

但是当我在视图中使用2个EACH循环而不是1时,它会严重失败。 preg_replace_callback()将匹配第一个开始标记和第二个循环的最后一个结束标记,并给出如下字符串:

"htmlbalalbal {{#EACH}} more htmlblabla {{EACH newsitems}} htmlblalblabla"

来自:

<div class="rows-container">
{{each slides}}
    <div class="row flex-wrap" data-id="{{id}}">
    </div>
{{#each}}
</div>
<div class="rows-container">
{{each blogposts}}
    <div class="row flex-wrap" data-id="{{id}}">
    </div>
{{#each}}

我一直在尝试改变正则表达式一段时间了,我开始看到越来越多的逻辑......但我还没有解决我的问题。是否有可能走这条路?或者我是否需要另一种解决方案来扫描我的测试文件中的多个EACH循环? 我可能很快会使用一些框架,但是当我在周末感到无聊时,我喜欢这样做...

class Aclass{

    private $each = '~\{\{each ([^{]*)\}\}([^*]*)\{\{\#each\}\}~i';

    private $current_file_content = "";
    private $testviews = ['/testview.php'];

    private $views;

    function __construct($views){
        $this->views = $views; //not in use
        $this->start();
   }

   private function start(){
        foreach($this->testviews as $file){
            $this->current_file_content = file_get_contents(ROOT.$file);
            $this->scan_each();
        }
   }

   private function scan_each(){
       $result = preg_replace_callback($this->each, [$this, '_each'], $this->current_file_content);
   }


    private function _each($matches){
        foreach($matches as $match){
            var_dump(htmlspecialchars($match));
            echo '<br><br>';
        }
    }

编辑:16-5 所以,我一直在走得更远......它工作得很好,但它并没有覆盖每个内部的每一个。这是一种类似的情况,我认为将来可能会有用:

{{each attributes}}
<label>{title}</label>
<select name="{key}" id="{key}" class="select">
    <option value="0" selected>choose an option</option>
    {{each values}}
        <option value="{id}" {selected}>{title}</option>
    {{#each}}
</select>
{{#each}}

我一直在想是否有办法在1个正则表达式中覆盖它,然后如果处理外部每个循环的函数看到每个内部的另一个,它将首先完成该1。我完全愿意自己构建这些功能,但获得一些技巧会很棒。你会建议分离正则表达式吗?找到{{each X}}和{{#each}}并在php中以另一种方式修复它,或修复已回答的Regex以便能够处理这个问题?

2 个答案:

答案 0 :(得分:3)

您的正则表达式可以修复为

'~{{each\s+([^{}]*)}}(.*?){{#each}}~is'

请参阅regex demo

这里的要点是,您在模式中使用的[^*]匹配除*之外的任何字符,而您需要匹配一个字符串与另一个字符串之间的任何0+字符。可以使用.*?s修饰符来实现。

<强>详情:

  • {{each - 文字子字符串
  • \s+ - 1+空格
  • ([^{}]*) - 第1组:除{}以外的零个或多个字符
  • }} - 文字}}子字符串
  • (.*?) - 第2组:任何0+字符,尽可能少(由于懒惰的*?量词
  • {{#each}} - 文字{{#each}}子字符串。

答案 1 :(得分:1)

用以下代码替换您的代码:

private $each = '~{{each\s+(.+?)}}(.+?){{#each}}~is';

RegEx101 Demo