我有点谜题,或许不是。 检查这件作品:
$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设置有关,但我已经尝试过了,并没有改变。
EDIT2。崩溃是浏览器中的“连接中断”。没有完整的服务器崩溃,但脚本执行暂停。再次,日志中没有错误。
问题解决了。我不得不在最后用/ s替换(。| \ n)。非常感谢你们!
答案 0 :(得分:2)
虽然在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。然后,您只需使用.
即可匹配任何内容,包括换行符。而不是2 ^ n种可能性,它只需要检查n种可能性。
注意:一些正则表达式引擎足够聪明,可以避免这个陷阱。理论上如果第二个“选择”不存在,引擎应该足够聪明,知道它永远不会匹配,因此放弃。例如,当我在Perl中测试它时,没有问题。上面的PHP正则表达式测试程序没有问题。但也许您的PHP版本较旧,而且不太优化。
答案 1 :(得分:0)
如果真的崩溃,你会看到至少一些消息。我猜,你根本看不到输出。这是因为你的正则表达式不起作用。
您可以通过删除正则表达式中的最终\bselect\b
或将select
附加到$query
来修复此问题。然后输出一些匹配。