模式适用于 regex101 但不适用于服务器

Pattern works on regex101 but not on Server

我的模式:

/{LOOP:(\w+)[^}]*}((\s*?.?)*?){\/LOOP:}/

我的测试字符串:

<tbody>
    {LOOP:MENU}
    <tr>
        <td>{VAR:ID}</td>
        <td>{VAR:NAME}</td>
        <td>{VAR:ROLLE}</td>
        <td>{VAR:ACTIONS}</td>
    </tr>
    {/LOOP:MENU}
</tbody>

当您在 regex101 上尝试时,它可以正常工作。但是当我在我的服务器上使用 preg_match_all() 尝试它时,它不起作用。 preg_last_error() returns:

2(PREG_BACKTRACK_LIMIT_ERROR).

regex101 告诉我“581 步中的 1 场比赛”怎么可能?还是步数与回溯无关?

我正在使用 PHP 版本 5.5.9-1ubuntu4.16 的 apache2 服务器。

在我的php.ini中,pcre.backtrack_limit设置为1000000。

编辑:

根据 Alan Moore 的提示,我现在使用以下模式:

/{LOOP:(\w+)[^}]*}(.*?){\/LOOP:}/s

这返回 0(NO_ERROR)。但是在我的服务器上它现在不匹配任何东西。为什么它在 regex101 上工作但在我的服务器上不工作?

PHP:

$test="<tbody>
        {LOOP:MENU}
        <tr>
            <td>{VAR:ID}</td>
            <td>{VAR:NAME}</td>
            <td>{VAR:ROLLE}</td>
            <td>{VAR:ACTIONS}</td>
        </tr>
        {/LOOP:MENU}
       </tbody>"
preg_match_all("/{LOOP:(\w+)[^}]*}(.*?){\/LOOP:}/s", $test, $matches, PREG_SET_ORDER);
// $matches is now an emty array.

它可能不起作用,因为您的服务器的正则表达式引擎将 {} 处理为描述有限重复的特殊字符(另请参阅 Regex Tutorial)。而 Regex101 页面做了一些假设。

当想要匹配 {} 作为字符时,它们需要像 \{\} 一样被转义,或者像 [{}] 然后他们被当作普通字符对待。

我建议转义这些字符,如下所示:

\{LOOP:(\w+)[^}]*\}((\s*?.?)*?)\{\/LOOP:\}

这个表达式也适用于 Regex101

注意: 某些风格的正则表达式将允许不匹配的 } 作为字符进行匹配,因此它可能不需要转义,但我发现它是逃避它的最佳实践。

php 在正则表达式中需要一个额外的反斜杠。在这种情况下,将 </code> 更改为 <code>\1 有效:

preg_match_all("/{LOOP:(\w+)[^}]*}(.*){\/LOOP:(\1)}/s", ...

或者,单反斜杠在这里可以用单引号引起来,您可以通过始终在正则表达式周围使用单引号来省去一些麻烦:

preg_match_all('/{LOOP:(\w+)[^}]*}(.*){\/LOOP:()}/s', ...