php ltrim 破坏正则表达式?

标签 php regex trim

我有一个谜题要问你,或者也许没有。 检查这一部分:

$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); 没有这条线,一切正常。

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

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

有人能解释一下吗?

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

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

问题已解决。我必须在最后用/s 替换 (.|\n) 。非常感谢大家!

最佳答案

PHP regex tester 中对此进行测试时不会造成任何问题,我认为这可能是由于你形成表达方式而导致的崩溃。考虑这个结构:

(.|\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 开关,如 primo 在评论中建议的那样。然后您可以简单地使用 . 来匹配包括换行符在内的任何内容。它只需检查 n 个可能性,而不是 2^n 个可能性。

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

关于php ltrim 破坏正则表达式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13856025/

相关文章:

java - String.trim() 不仅删除 Java 中的空格

php - VMWare 6.5 + PHP 5.3.3 + Symfony 1.4 出现奇怪的 PHP 解析/语法错误

php - wordpress 登录页面未获取 load-styles.php?

javascript正则表达式允许至少一个特殊字符和一个数字

javascript - 如何在将拆分器保留在数组中的同时通过正则表达式拆分字符串

MySQL:更新列 WHERE 列以 ""开始(空格)

python - 2D 或 3D 中的 Numpy trim_zeros

javascript - DataTables javascript 无法应用于重复表

php - 从 HTTP 重定向到 HTTPS(最好的方法是 .htaccess 或 PHP 重定向代码)

regex - 使用replaceMatchesInString循环