Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 如何使用preg_match提取自定义标记_Php_Regex_Preg Match - Fatal编程技术网

Php 如何使用preg_match提取自定义标记

Php 如何使用preg_match提取自定义标记,php,regex,preg-match,Php,Regex,Preg Match,我使用此模式'/(\{(\w+)\}(.*)?\{%(\w+)%\}(.*)\{\/(\w+)\})/i'使用preg\u match函数从模板中提取标记 样本模板: <table id="middle" cellspacing="0px" cellpadding="0px"> {middle} <tr> {left}<td>{%left%}</td>{/left} <td>{%middl

我使用此模式
'/(\{(\w+)\}(.*)?\{%(\w+)%\}(.*)\{\/(\w+)\})/i'
使用
preg\u match
函数从模板中提取标记

样本模板:

<table id="middle" cellspacing="0px" cellpadding="0px">
    {middle}
    <tr>
        {left}<td>{%left%}</td>{/left}
        <td>{%middle%}{%content%}</td>
        {right}<td>{%right%}</td>{/right}
    </tr>
    {/middle}
</table>

{中间}
{left}{%left%}{/left}
{%middle%}{%content%}
{right}{%right%}{/right}
{/middle}
如何确保每个标记的
开始
结束
与其名称真正匹配

在本例中,
middle
标记同时匹配
middle
content
,而它应该只匹配
middle
tag

,我认为解决此问题的最佳方法是通过几个不同的步骤来完成

首先,您应该使用with
/(?>{([^}]+)})(.*){\/\1}/sim
作为正则表达式。这将找到顶层{tag}{/tag}。$matches[2]将包含内容(不包含标记),而$matches将包含标记本身

您应该创建一个递归调用的函数,以便在回调中,在$matches[2]上再次调用它,以便查找子项{tags},以防有更多子项。这就是你穿过这棵树的方法

最后,您应该创建第三个函数来处理{%tag%}。我将再次使用preg_replace_回调,并使用switch语句处理标记名

这将为您指明正确的方向

编辑:这里是我上面描述的功能完整的演示:\

<?php

$content = <<<END
{a}
  {b}I like {%first%} {%last%} a {c}lot{/c}.{/b}
{/a}
END;

echo find_tags($content);

function find_tags($content)
{
  return preg_replace_callback('/(?>{([^}]+)})(.*)?{\/\1}/sim', 'find_tags_callback', $content);
}

function find_tags_callback($matches)
{
  // Find and process any children tag pairs.
  $matches[2] = find_tags($matches[2]);

  // Process the tags {%tag%}.
  $matches[2] = preg_replace_callback('/{%([^%]+)%}/sim', 'process_tags', $matches[2]);

  switch ( $matches[1] )
  {
    case 'a':
      $tag = 'div';

      break;
    case 'b':
      $tag = 'p';

      break;
    case 'c':
      $tag = 'b';

      break;
  }

  return '<'.$tag.'>'.$matches[2].'</'.$tag.'>';
}

function process_tags($matches)
{
  switch ( $matches[1] )
  {
    case 'first':
      return 'Francois';

      break;
    case 'last':
      return 'Deschenes';

      break;
  }
}

//

我认为解决这个问题的最好方法是通过几个不同的步骤来完成

首先,您应该使用with
/(?>{([^}]+)})(.*){\/\1}/sim
作为正则表达式。这将找到顶层{tag}{/tag}。$matches[2]将包含内容(不包含标记),而$matches将包含标记本身

您应该创建一个递归调用的函数,以便在回调中,在$matches[2]上再次调用它,以便查找子项{tags},以防有更多子项。这就是你穿过这棵树的方法

最后,您应该创建第三个函数来处理{%tag%}。我将再次使用preg_replace_回调,并使用switch语句处理标记名

这将为您指明正确的方向

编辑:这里是我上面描述的功能完整的演示:\

<?php

$content = <<<END
{a}
  {b}I like {%first%} {%last%} a {c}lot{/c}.{/b}
{/a}
END;

echo find_tags($content);

function find_tags($content)
{
  return preg_replace_callback('/(?>{([^}]+)})(.*)?{\/\1}/sim', 'find_tags_callback', $content);
}

function find_tags_callback($matches)
{
  // Find and process any children tag pairs.
  $matches[2] = find_tags($matches[2]);

  // Process the tags {%tag%}.
  $matches[2] = preg_replace_callback('/{%([^%]+)%}/sim', 'process_tags', $matches[2]);

  switch ( $matches[1] )
  {
    case 'a':
      $tag = 'div';

      break;
    case 'b':
      $tag = 'p';

      break;
    case 'c':
      $tag = 'b';

      break;
  }

  return '<'.$tag.'>'.$matches[2].'</'.$tag.'>';
}

function process_tags($matches)
{
  switch ( $matches[1] )
  {
    case 'first':
      return 'Francois';

      break;
    case 'last':
      return 'Deschenes';

      break;
  }
}

//

1我确信,但不确定,为了确保封闭标记({this}{/this})与数据标记({%this%})匹配,您需要一个附带的if语句来测试返回的字符串

我会使用preg_replace_回调函数,如下所示:

<?php
$str = '<template contents>';
$newstr = preg_replace_callback(
'/(\{(\w+)\}(.*))?\{%(\w+)%\}((.*)\{\/(\w+)\})?/i', 
'check', //<-- the function to send matches to
$str);
function check($matches){
    if($matches[1] == $matches[2] && $matches[1] == $matches[3]){
        /*Do Work*/
        return ''; //new formatted string to send back to the $newstr var
    }
}
?>


preg_replace_回调函数将作为数组找到的任何匹配项发送到指定函数进行处理,然后您从该函数返回新的格式化字符串。

1我确信,但不确定,要确保封闭标记({this}{/this})与数据标记({%this%})匹配,您需要一个附带的if语句来测试返回的字符串

我会使用preg_replace_回调函数,如下所示:

<?php
$str = '<template contents>';
$newstr = preg_replace_callback(
'/(\{(\w+)\}(.*))?\{%(\w+)%\}((.*)\{\/(\w+)\})?/i', 
'check', //<-- the function to send matches to
$str);
function check($matches){
    if($matches[1] == $matches[2] && $matches[1] == $matches[3]){
        /*Do Work*/
        return ''; //new formatted string to send back to the $newstr var
    }
}
?>


preg_replace_回调函数将作为数组找到的任何匹配项发送到指定函数进行处理,然后从该函数返回新的格式化字符串。

不需要if语句。这样做实际上会导致许多无效匹配,特别是:{a}{b}{/b}{/a}将导致{a}{/b}。你需要调查一下。看我的例子。如果标记位于多行上,此解决方案也将不起作用。您不需要if语句。这样做实际上会导致许多无效匹配,特别是:{a}{b}{/b}{/a}将导致{a}{/b}。你需要调查一下。看我的例子。如果标记位于多行上,此解决方案也不起作用。