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}。你需要调查一下。看我的例子。如果标记位于多行上,此解决方案也不起作用。