Php 相对简单的Preg_match_会导致502坏网关

Php 相对简单的Preg_match_会导致502坏网关,php,regex,whitespace,preg-match-all,bad-gateway,Php,Regex,Whitespace,Preg Match All,Bad Gateway,我有一个preg_match_所有函数与模式: preg_match_all( '/\[(if) ([^\]]*)\] ((?:(?!\[if).|(?R))*?) \[endif\]/sx', $text, $matches ); 我猜这是一个非常简单的模式,它寻找语法[if condition]sometext[endif],但它也支持嵌入ifs f.e.[if condition1]aa[if condition2]bb[endif][endif]

我有一个preg_match_所有函数与模式:

preg_match_all(
    '/\[(if) ([^\]]*)\]
    ((?:(?!\[if).|(?R))*?)
    \[endif\]/sx',
    $text,
    $matches
);
我猜这是一个非常简单的模式,它寻找语法
[if condition]sometext[endif]
,但它也支持嵌入ifs f.e.
[if condition1]aa[if condition2]bb[endif][endif]
。我使用s开关将换行符视为点(因为我希望它可以工作多行)和x,以便于阅读(但删除x并不能解决问题)

对于我拥有的大多数输入数据,它都可以正常工作,但对于某些特定的输入,它会在nginx服务器上导致502坏网关错误,并且日志中没有任何错误或异常。我使用的是nginx+phpfpm(5.6.15-1+deb.sury.org~trusty+1),但在php7上也是如此

这里是导致502坏网关错误的PHP代码,您可以很容易地检查它,非常简单,只是一个变量和正则表达式

请确保您以1:1的比例复制了包含所有空格、选项卡等的内容

最重要的是,您可以删除几乎任何一行,甚至删除一个缩进(任何地方的任何几个空格),以使其正常工作


我不知道这里出了什么问题,我可以创建一个文件来演示我的问题,但不知道如何解决它。

您的正则表达式包含一个“缓和”点模式的负前瞻。但是,您未能向其添加结束分隔符,因此,它变得相当“重”

我建议在前瞻检查中添加结束分隔符(
[endif]
):

\[(if)\s+([^\]]*+)\]((?>(?!\[(?:end)?if\b).|(?R))*)\[endif\]
                             ^^^^^^^^

或者,您甚至可以将回火贪婪令牌展开为

\[(if)\s+([^\]]*+)\]((?>[^[]++(?:\[(?!(?:end)?if\b)[^[]*)*|(?R))*)\[endif\]
请参阅(但是,如果
[
可以跟随
[if…]
,则它将不起作用)


另外,请注意,您的正则表达式在
之后有一个空格(如果)
由于您使用的是
/x
修饰符,因此它不被视为一个文本空间,而是被忽略。这就是为什么我将其更改为
\s+

我无法在eval上复制它。in:@jeroen对,令人惊讶的是,它在使用php时工作得很好,只是检查了使用
php test.php
运行,并且它按预期工作。问题发生在当使用php fpm(nginx/1.8.0)通过nginx打开文件时,请尝试甚至。@WiktorStribiż查看您的解决方案是否有效,谢谢!