2

我有一个谜题要问你,也许没有。检查这块:

$query = ' SELECT account.account_no,
       account.accountname,
       accountbillads.bill_city,
       account.website,
       account.phone,
       CASE
         WHEN ( users.user_name NOT LIKE "" ) THEN users.user_name
         ELSE groups.groupname
       END AS user_name,
       entity.crmid,
       account.accountid,
       account.parentid,
       partner.partnerid      
FROM   account
       INNER JOIN entity
               ON entity.crmid = account.accountid
       INNER JOIN currency_info AS CurrencyInfoTable
               ON CurrencyInfoTable.id =
                  entity.record_currency_id
WHERE  entity.deleted = 0   ';

$query = ltrim($query);

preg_match("/^select ((.|\n)*?)\bfrom\b((.|\n)*?)\bselect\b/i", $query, $matches);

print('finito');
print_r($matches);

在我的服务器上,这崩溃了,没有任何错误。

令人惊讶的是,棘手的行是 $query = ltrim($query); 没有这条线,一切正常。

这还有几件事:正则表达式的敏感部分是对“选择”的最后不贪婪搜索。如果找不到第二个选择,则崩溃。查询的长度很重要。另外,请注意,在同一台机器上运行 phpunits 时,不存在此问题。

我的聚会是ltrim对字符串做了一些事情,但我不确定是什么。

有人可以解释一下吗?

编辑。好吧,看来 ltrim 不是问题。如果我只给出没有起始空白的字符串,我就会崩溃。它可能与 pcre.backtrack_limit 和 pcre.recursion_limit 设置有关,但我已经尝试过了,但没有改变。

编辑2。崩溃是浏览器中的“连接中断”。没有完整的服务器崩溃,但脚本执行停止。同样,日志中没有错误。

问题解决了。最后我不得不用 /s 替换 (.|\n) 。非常感谢你们!

4

2 回答 2

2

虽然在PHP 正则表达式测试器中对此进行测试不会导致任何问题,但我认为这可能是由于您形成表达式的方式而导致的崩溃。考虑这个结构:

(.|\n)*?

潜在的问题是|运营商,结合*. 当它不匹配时,这可能会产生大量的可能性:

                    first character matches .
                               |
                          yes------no
                           |        |
         2nd character matches .    first character matches \n
                 |                                 |
            yes-----no                       yes--------no
             |       |                        |          |
      3rd char .    2nd char \n     2nd char matches .  2nd char matches .

正则表达式引擎必须检查 2^n 种可能性,其中 n 是字符串中剩余的字符数。

解决方案是使用/s开关,正如评论中最初建议的那样。然后你可以简单地使用.来匹配任何东西,包括换行符。而不是 2^n 的可能性,它只需要检查 n 的可能性。

注意:一些正则表达式引擎足够聪明,可以避免这个陷阱。理论上,如果第二个“选择”不存在,引擎应该足够聪明,知道它永远无法匹配并因此放弃。例如,当我在 Perl 中对其进行测试时,没有问题。并且上面的 PHP 正则表达式测试器没有问题。但也许您的 PHP 版本较旧并且没有那么优化。

于 2012-12-13T09:25:20.777 回答
0

如果它真的崩溃了,你至少会看到一些消息。我猜,你根本看不到任何输出。这是因为您的正则表达式不起作用。

您可以通过删除\bselect\b正则表达式中的 final 或将 a 附加select到您的$query. 然后它输出一些匹配。

于 2012-12-13T09:08:12.653 回答