我正在尝试在php模板系统中进行条件语句,但是我在使其工作时遇到了一些问题。
我的语法是(condition? value to show if condition is true)
。使用此模式可以轻松完成匹配:\((\w+)\?(.+?)\)
。问题是我需要它以递归方式工作。
我在字符串(it should be (a?working(b? with nested conditions).))
上尝试了这些模式:
\((\w+)\?(.+?|(?R))\)
但匹配(a?working(b? with nested conditions)
(最后跳过.)
)
\((\w+)\?(.+|(?R))\)
但它与(a?working(b? with nested conditions).))
匹配(直到最后)
)。
帮助我,我被困住了。
答案 0 :(得分:1)
尝试以下模式:
\((\w+)\?([^()]|\((?!\w+\?)|(?R))+\)
编辑:确定尝试将模式更改为以下模式:
\((\w+)\?(.+|\((?!\w+\?)|(?R))+\)
^^
如果这也不起作用,请尝试将.+
更改为.+?
。如果所有这些对您不起作用,那么您可能(我认为这是更好的解决方案)需要使用解析器而不是正则表达式。
答案 1 :(得分:0)
正如@Sniffer所说,我做了一个解析器。这很麻烦,但做得很好。它是模板系统类的一部分。 $this->rendered
是正在解析的字符串。
const COND_START = '((';
const COND_END = '))';
const COND_SEP = '?';
const COND_NOT = '!';
private function parseConditionals()
{
for (
$i=0,
$level=0,
$levelstart=array(0=>0),
$levelseparator=array(0=>0),
$levelname=array(0=>'__main__');
$i < strlen($this->rendered);
) {
$startpos = strpos($this->rendered, self::COND_START, $i);
$seppos = strpos($this->rendered, self::COND_SEP, $i);
$endpos = strpos($this->rendered, self::COND_END, $i);
if ( ($startpos === FALSE) && ($endpos === FALSE) ) {
$i = strlen($this->rendered);
} elseif ( ($startpos !== FALSE) && $startpos < $endpos ) {
if ( $seppos < $endpos ) {
$level++;
$levelstart[$level] = $startpos;
$levelseparator[$level] = $seppos;
$levelname[$level] = substr(
$this->rendered,
$startpos+strlen(self::COND_START),
$seppos-$startpos-strlen(self::COND_START)
);
$i = $seppos + strlen(self::COND_SEP);
} else {
$i = $startpos + strlen(self::COND_START);
}
} else {
$originallen = strlen($this->rendered);
if ( $level > 0 ) {
$not = false;
if ( strpos($levelname[$level], self::COND_NOT) === 0 ) {
$levelname[$level] = substr($levelname[$level], strlen(self::COND_SEP));
$not = true;
}
if (
!$this->get($levelname[$level]) == $not
) {
$this->rendered = substr_replace(
$this->rendered,
'',
$endpos,
strlen(self::COND_END)
);
$this->rendered = substr_replace(
$this->rendered,
'',
$levelstart[$level],
$levelseparator[$level]-$levelstart[$level]+strlen(self::COND_SEP)
);
} else {
$this->rendered = substr_replace(
$this->rendered,
'',
$levelstart[$level],
$endpos-$levelstart[$level]+strlen(self::COND_END)
);
}
$level--;
}
$i = $endpos + strlen(self::COND_END);
$i += strlen($this->rendered)-$originallen;
}
}
}