PHP正则表达式捕获模板标记和if语句标记
我在html文件中有这样的标签,放在整个文件中PHP正则表达式捕获模板标记和if语句标记,php,regex,Php,Regex,我在html文件中有这样的标签,放在整个文件中 *|SUBJECT|* *|SUBJECT|* *|IFNOT:ARCHIVE_PAGE|* *|ARCHIVE|* *|END:IF|* *|FACEBOOK:PROFILEURL|* *|TWITTER:PROFILEURL|* *|FORWARD|* *|IF:REWARDS* *|REWARDS|* *|END:IF|* 使用这个PHP函数和正则表达式,我可以得到所有标记的结果 preg_match_all("/\*\|(
*|SUBJECT|*
*|SUBJECT|*
*|IFNOT:ARCHIVE_PAGE|*
*|ARCHIVE|*
*|END:IF|*
*|FACEBOOK:PROFILEURL|*
*|TWITTER:PROFILEURL|*
*|FORWARD|*
*|IF:REWARDS*
*|REWARDS|*
*|END:IF|*
使用这个PHP函数和正则表达式,我可以得到所有标记的结果
preg_match_all("/\*\|(.*?)\|\*/", $this->template, $elements);
$this->elements["Tags"] = $elements[0];
$this->elements["TagNames"] = $elements[1];
我想要的是找到一种方法来捕获IF:(TAG)语句和IFNOT:(TAG)语句以及内容
到目前为止,我得到的是
ergex=> /\*\|IF(([A-Z{0-3}]):([A-Z_]+))\|\*(.*?)\*\|END:IF\|\*|\*\|(.*?)\|\*/g
但是它只捕捉到标签本身,作为一个整体,任何人都可以为我指出正确的方向或帮助我。正如我在评论中提到的那样,你的方法过于简单,我可以让你开始使用我用于这些事情的方法。它更像是一种标记器/词法分析器/解析器方法 这听起来既大又可怕,但实际上让事情变得更简单了
<?php
function parse($subject, $tokens)
{
$types = array_keys($tokens);
$patterns = [];
$lexer_stream = [];
$result = false;
foreach ($tokens as $k=>$v){
$patterns[] = "(?P<$k>$v)";
}
$pattern = "/".implode('|', $patterns)."/i";
if (preg_match_all($pattern, $subject, $matches, PREG_OFFSET_CAPTURE)) {
//print_r($matches);
foreach ($matches[0] as $key => $value) {
$match = [];
foreach ($types as $type) {
$match = $matches[$type][$key];
if (is_array($match) && $match[1] != -1) {
break;
}
}
$tok = [
'content' => $match[0],
'type' => $type,
'offset' => $match[1]
];
$lexer_stream[] = $tok;
}
$result = parseTokens( $lexer_stream );
}
return $result;
}
function parseTokens( array &$lexer_stream ){
$result = [];
$mode = 'none';
while($current = current($lexer_stream)){
$content = $current['content'];
$type = $current['type'];
switch($type){
case 'T_WHITESPACE':
next($lexer_stream);
break;
case 'T_TAG_START':
$mode = 'start';
next($lexer_stream);
break;
case 'T_WORD':
if($mode == 'start') echo "Tag $content\n";
if($mode == 'ifnot') echo "IfNot $content\n";
next($lexer_stream);
break;
case 'T_TAG_END':
$mode = 'none';
next($lexer_stream);
break;
case 'T_IFNOT':
$mode = 'ifnot';
next($lexer_stream);
break;
case 'T_EOF': return;
case 'T_UNKNOWN':
default:
print_r($current);
trigger_error("Unknown token $type value $content", E_USER_ERROR);
}
}
if( !$current ) return;
print_r($current);
trigger_error("Unclosed item $mode for $type value $content", E_USER_ERROR);
}
$subject = '*|SUBJECT|*
*|SUBJECT|*
*|IFNOT:ARCHIVE_PAGE|*
*|ARCHIVE|*
*|END:IF|*
*|FACEBOOK:PROFILEURL|*
*|TWITTER:PROFILEURL|*
*|FORWARD|*
*|IF:REWARDS*
*|REWARDS|*
*|END:IF|*';
$tokens = [
'T_WHITESPACE' => '[\r\n\s\t]+',
'T_TAG_START' => '\*\|',
'T_TAG_END' => '\|\*',
'T_IF' => 'IF:',
'T_IFNOT' => 'IFNOT:',
'T_ENDIF' => 'END:IF',
'T_WORD' => '\w+',
'T_EOF' => '\Z',
'T_UNKNOWN' => '.+?'
];
parse($subject,$tokens);
而不是我所拥有的,但它可能必须在:
'T_TAG_START' => '\*\|',
因为该标记将首先匹配它
也别忘了把放在下一个($lexer\u stream)代码>否则它将是一个无限循环。在嵌套结构(如数组)中,有必要使用while和next来控制数组指针
祝你好运,快乐 这是什么来源?你的第一个正则表达式已经捕获了普通和IF“模板标签”。匹配嵌套组对处理没有必要的帮助。而是按顺序循环所有结果,然后应用逻辑。-还有,是的,你是如何得到这样一个模板化的迷你语言的?编写您自己的标记器和解释器是一种毫无意义的结束方式(即查看调查的当前状态)。您使用的基本方法过于“简单化”,您应该采用标记方法。您可以参考这个基本的lexer/parser,这是我的灵感来源,我在另一个问题上使用它作为JSON对象解析器,版本如下:
'T_IFNOT' => '\*\|IFNOT:',
'T_TAG_START' => '\*\|',