【问题标题】:Pattern works on regex101 but not on Server模式适用于 regex101 但不适用于服务器
【发布时间】:2016-05-06 22:41:04
【问题描述】:

我的模式:

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

我的测试字符串:

<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() 返回:

2(PREG_BACKTRACK_LIMIT_ERROR)。

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

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

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

编辑:

按照 Alan Moore 的建议,我现在使用以下模式:

/{LOOP:(\w+)[^}]*}(.*?){\/LOOP:\1}/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:\1}/s", $test, $matches, PREG_SET_ORDER);
// $matches is now an emty array.

【问题讨论】:

  • ((\s*?.?)*?) 太复杂了。只需使用 (.*?) 并添加 s 修饰符。

标签: php regex preg-match-all pcre


【解决方案1】:

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

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

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

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

【讨论】:

    【解决方案2】:

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

    当想要将{} 作为字符进行匹配时,它们需要像\{\} 一样被转义,或者像[{}] 这样被塞进方括号中,然后它们就会被当作普通字符对待。

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

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

    这个表达式也适用于Regex101

    注意:某些正则表达式允许不匹配的} 作为字符匹配,因此它可能不需要转义,但我发现最好的做法是转义它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-30
      相关资源
      最近更新 更多