正则表达式/ preg_match_all,带可选匹配

时间:2013-12-04 02:35:24

标签: php regex

我正在尝试为我的网站用户创建一个非常小的模板系统,允许他们在内容中添加变量。

我想要的是在php中运行以下内容的正则表达式:

<p>Hi {{ user.name | fallback="awesome person" }}!</p>

至少会给我以下项目:

  1. {{user.name | fallback =“awesome person”}}
  2. user.name
  3. 很棒的人
  4. 这也需要匹配以下内容:

    <p>Your site is {{ site.name }}</p>

    哪会让我回来:

    1. {{site.name}}
    2. site.name
    3. 我会添加我尝试的所有内容,但每次尝试我都基本上覆盖了最后一次尝试,正则表达式不是我的强项!

      理想情况下,我会在整个内容上运行正则表达式,它会返回一个包含所有匹配项的数组,因此我可以循环遍历并用$data[(2)]替换(1),除非(2) )不存在,在这种情况下,我将添加(3)后备。

      例如,如果我的数组中存在user.name,则响应为

      Hi Frank!
      

      如果没有,响应将是

      Hi awesome person!
      

      我可以处理循环/替代等问题,这是我需要帮助的原始正则表达式,任何想法?

      理想情况下,空格也是可选的,即{{user.name|fallback="awesome person"}}也可以使用

1 个答案:

答案 0 :(得分:3)

一种很好的方法是使用preg_replace_callback()

$txt = 'Hello {{ user.name | fallback="awesome person" }}';

$context = array(
        'user.name' => 'Jack',
);

$re = '/{{\s*([a-z.]+)(?:\s*\|\s*fallback="([^"]+)")?\s*}}/';

echo preg_replace_callback($re, function($match) use ($context) {
        if (isset($context[$match[1]])) {
                return $context[$match[1]];
        } elseif (isset($match[2])) {
                return $match[2];
        } else {
                return '';
        }
}, $txt);

每次文本的一部分与您的表达式匹配时,它将调用一个匿名函数,该函数将根据给定的$context返回结果。

关于表达的一个小解释:

/{{\s*([a-z.]+)(?:\s*\|\s*fallback="([^"]+)")?\s*}}/
       ^--+--^ ^------------+-------|--+--|--^
          |                 |          |
          |                 |     (fallback value)
          |                 |
      (variable name) (optional fallback segment)