我目前正在研究一个简单的PHP模板引擎,并希望替换所有
{% include file="anotherTemplate.tpl" %}
与给定模板的内容。对于此任务,我使用正则表达式。
private $funcSeparatorL = '{%';
private $funcSeparatorR = '%}';
// ...
preg_match('/' . $this->funcSeparatorL . ' include file="(.*)'.(.*)" ' . $this->funcSeparatorR . '/', $this->content)
这工作正常,但显然只有分隔符和中间内容之间的单个空格。我希望能够使用多个空格来使整个事情更耐错。
但是,如果我使用 .*
来匹配多个字符,整个页面将永远加载并且永远不会完成。
preg_match('/' . $this->funcSeparatorL . '.*include file="(.*)'.(.*)".*' . $this->funcSeparatorR . '/', $this->content)
.*
是处理此类任务的正确方法吗?如果是,为什么会导致此类错误?
而不是.*
,只需使用 's*
。这只会匹配空间并避免灾难性的回溯,这就是您当前问题的原因。
例:
preg_match('/' . $this -> funcSeparatorL . ''s*include file="(.*)'.(.*)".*' . $this -> funcSeparatorR . '/', $this -> content);
顺便说一句,您可以通过摆脱所有其他.*
来进一步改进整个正则表达式,或者在可能的情况下使它们不贪婪。未经测试的示例:
preg_match('/' . $this -> funcSeparatorL . ''s*include file="([^"]*?)'.([^"]*)".*?' . $this -> funcSeparatorR . '/', $this -> content);
这是一个演示。
您可以通过将最后一个.*?
替换为 [^}]*
来进一步改进这一点,但这取决于您是否允许嵌套模板表达式。
经验法则:如果你在没有非贪婪限定符(?
)的情况下输入.+
或.*
,那么你做错了什么的可能性非常高。