2016-06-12 17 views
0

私はテンプレートエンジンを持っています。 tplファイルの解析。しかし、tplファイルに{if}、{foreach}または{language}ブロックがたくさんある場合、preg_matchはapacheを破棄します。preg_matchクラッシュapache

これは私のpreg_match関数です。

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

と私はエラーなしregex101.com、そのsuccesfulyマッチングをしようとすると、これは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. 

ですが。 https://regex101.com/r/uW8rZ8/3

+0

が、私はこの部分を考える[ '\ {(IF | foreachの)[\ s]は*(*。 ?)[\ s] * \} '](https://regex101.com/r/rN1kM8/1)は多くのバックトラックを引き起こしています。代替:['{foreach} \ s *([^}] * [^} \ s])\ s *}'](https://regex101.com/r/rN1kM8/2)素晴らしい回答はすでに( –

答えて

1

あなたのパターンはregex101で動作している場合でも、あなたは壊滅的なbactrackingの近くにあります。あなたがパターンをregex101で動作させ、あなたのサーバで動作させない理由は簡単です。構成は同じではありません。

2つのことは、あなたのパターンに欠けている:

  • 所有数量(または原子団)の使用、それは有用ではありませんどこバックトラック禁止します。
  • (?: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、あなたの正規表現はおそらく破局的にバックトラッキングを意味します。そうでない場合は、適切なツールを使用していない可能性があります... 実際のパーサーを使用することを検討しましたか?再帰的マッチングを扱うように設計されたもの?

にはが必要ですが、正規表現を使用する必要がある場合は、いくつかの欠陥を修正する必要があります。

私は設定に慣れていないので、あなたが得ているエラーを直接手助けする必要があります(エラーでもですか?)。しかし、私はあなたが他のものに取り組む前にいくつかのより緊急な問題を解決する必要があると思います問題。このプロセスは、おそらく関連している可能性があるため、問題が解決する可能性があります。

あなたの正規表現はです。わかりやすいのはです。あなたの正規表現が何をしているのかわかりません。私はあなたの平均的なプログラマーではありません...私は正規表現を愛し、私は通常それを簡単に読むことができます。しかし、この1つではありません。 (問題の一部は、また、それはあなたがこの正規表現を使用しているなぜ本当にはっきりしていないという事実かもしれません。)

私の最初の提案はあなたのように、あなたがスペースを使用することができます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