2016-06-12 61 views
0

我有一个模板引擎。解析tpl文件。但是,当tpl文件有很多{if},{foreach}或{language}块preg_match粉碎apache。preg_match暗恋阿帕奇

这是我的preg_match函数;

preg_match_all('$\{(if|foreach)[\s]*(.*?)[\s]*\}((?:[^{]*(?:\{(?!\/?(if|foreach)[^}]*\})[^{]*)*|(?R))*)\{\/\1\}$iu',$content,$output); 

这是Apache日志

[Sun Jun 12 21:04:41.135620 2016] [mpm_winnt:notice] [pid 1888:tid 552] AH00428: Parent: child process 7620 exited with status 255 -- Restarting. 
[Sun Jun 12 21:04:41.235425 2016] [mpm_winnt:notice] [pid 1888:tid 552] AH00455: Apache/2.4.9 (Win64) PHP/5.5.12 configured -- resuming normal operations 
[Sun Jun 12 21:04:41.236426 2016] [mpm_winnt:notice] [pid 1888:tid 552] AH00456: Apache Lounge VC11 Server built: Mar 16 2014 12:42:59 
[Sun Jun 12 21:04:41.236426 2016] [core:notice] [pid 1888:tid 552] AH00094: Command line: 'c:\\wamp\\bin\\apache\\apache2.4.9\\bin\\httpd.exe -d C:/wamp/bin/apache/apache2.4.9' 
[Sun Jun 12 21:04:41.284459 2016] [mpm_winnt:notice] [pid 1888:tid 552] AH00418: Parent: Created child process 9668 
[Sun Jun 12 21:04:41.642877 2016] [mpm_winnt:notice] [pid 9668:tid 452] AH00354: Child: Starting 64 worker threads. 
[Sun Jun 12 21:04:42.047450 2016] [mpm_winnt:notice] [pid 1888:tid 552] AH00428: Parent: child process 9668 exited with status 255 -- Restarting. 
[Sun Jun 12 21:04:42.147702 2016] [mpm_winnt:notice] [pid 1888:tid 552] AH00455: Apache/2.4.9 (Win64) PHP/5.5.12 configured -- resuming normal operations 
[Sun Jun 12 21:04:42.147702 2016] [mpm_winnt:notice] [pid 1888:tid 552] AH00456: Apache Lounge VC11 Server built: Mar 16 2014 12:42:59 
[Sun Jun 12 21:04:42.147702 2016] [core:notice] [pid 1888:tid 552] AH00094: Command line: 'c:\\wamp\\bin\\apache\\apache2.4.9\\bin\\httpd.exe -d C:/wamp/bin/apache/apache2.4.9' 
[Sun Jun 12 21:04:42.194580 2016] [mpm_winnt:notice] [pid 1888:tid 552] AH00418: Parent: Created child process 10824 
[Sun Jun 12 21:04:42.487866 2016] [mpm_winnt:notice] [pid 10824:tid 452] AH00354: Child: Starting 64 worker threads. 

但是当我尝试regex101.com,它没有任何错误succesfuly匹配。 https://regex101.com/r/uW8rZ8/3

+0

我觉得这部分['\ {(如果|的foreach)[\ S] *(*。 ?)[\ s] * \}'](https://regex101.com/r/rN1kM8/1)导致了很多回溯。替代方法:['{(if | foreach)\ s *([^}] * [^} \ s])\ s *}'](https://regex101.com/r/rN1kM8/2)已经很好的答案(: –

回答

1

即使你的图案regex101工作,你是附近的灾难性bactracking。你使用regex101而不是在你的服务器上工作的原因很简单:配置不一样。

两件事情是缺少在您的模式:

  • 使用占有欲量词(或原子团)的禁止回溯它是没有用的。
  • 展开诸如(?:A|B)*A*+(?:BA*)*+之类的内容以避免交替并减少步骤数量。

遵循这些建议将会使你对3倍模式更高效:

~ 
{ (if\b|foreach\b) \s*+ 
([^\s}]*+ (?:\s+[^\s}]+)*+) \s* } 
(
    [^{]*+ 
    (?: { (?!/?if\b|/?foreach\b) [^{]* 
     | (?R)      [^{]*)*+ 

) 
{/\1} 
~ixu 

demo

1

Regex101可能没有任何错误地工作,但它运行不正常。如果你看一看,它说:2 matches - 10792 steps,这意味着你的正则表达式可能是灾难性的回溯。如果不是,那么你可能没有使用正确的工具...你有没有考虑使用实际的解析器?一个旨在处理递归匹配?

如果你仍然觉得这个需要用正则表达式来完成,你需要修复一些缺陷。

我不熟悉你必须直接帮助你解决错误的设置(他们甚至是错误吗?),但我认为你需要解决一些更紧迫的问题,然后才能解决其他问题的问题。这个过程有可能解决你所遇到的问题,因为它可能是相关的。

对我来说最重要的是你的正则表达式缺乏可读性。我不知道你的正则表达式是干什么的。而且我不是普通的程序员......我喜欢正则表达式,而且我通常能够轻松地阅读它们。但不是这个。 (部分问题也可能是一个事实,即它不是为什么你使用这个正则表达式是很清楚。)

我的第一个建议是使用x改性剂,它可以让你用的间距,就像你将在一个正常的程序。我已经修改了原来的正则表达式使用的间距,而我还去掉过多的反斜杠:

{(if|foreach) 
[\s]* 
(.*?) 
[\s]*} 
((?: 
    [^{]* 
    (?:{ 
    (?!/? 
     (if|foreach)[^}]*} 
    ) 
    [^{]* 
)*|(?R))* 
) 
{/\1} 

我写了一个类似的递归解析与过去正则表达式,所以我有这种类型的一些经验事情。从我记得以来,我的解析器速度更快,而且它的可读性更高(因为它的流动类似于BNF风格的解析器)。我想我现在该怎么东西是更快,基于关我的解析器:

$re = "` 
{(if)  ((?&exp))}(*PRUNE)\s*((?&line)*)\s*(*PRUNE){/if}| 
{(foreach)((?&exp))*}(*PRUNE)\s*((?&line)*)\s*(*PRUNE){/foreach} 
|(?&other)+ 

|(*F)(?: 
    (?'line' (?&if)|(?&for)|(?&other)+) 
    (?'if' {if  (?&exp)}(*PRUNE)\s*(?&line)*\s*(*PRUNE){/if}) 
    (?'for' {foreach(?&exp)}(*PRUNE)\s*(?&line)*\s*(*PRUNE){/foreach}) 
    (?'other' ([^{]+|{)(?! (/?if|/?foreach))) 
    (?'exp' [^}]*) 
)`xis"; 
+0

感谢您的建议,我正在努力 – redfox9999