我写这篇答案,是因为我遇到了相同的问题。正如Alan Moore所指出的,调整回溯和递归限制并不能解决这个问题。
当一个针头超过底层pcre库所限制的最大针头大小时,描述的错误就会发生。所述错误不是由php引起的,而是由底层pcre库引起的。这是错误信息#20,在这里进行了定义:
https://github.com/php/.../pcre_compile.c#L477
PHP在失败时只是打印了来自pcre库的错误文本。
但是,当我尝试使用先前捕获的片段作为针头并且它们大于32k字节时,就会出现此错误。
可以通过使用php cli中的这个简单脚本轻松测试。
<?php
$expand=$needle="_^b_";
while( ! preg_match( $needle, "Stack Exchange Demo Text" ) )
{
if ( strlen($expand) > 1024*64 ) die();
if ( $expand == "_^b_" ) $expand = "";
$expand .= "a";
$needle = '_^'.$needle.'_ism';
echo strlen($needle)."\n";
}
?>
要修复此错误,需要降低所得到的搜索模式,或者 - 如果需要捕获所有内容 - 则需要使用带有额外
偏移量参数的多个 preg_match。
<?php
if (
preg_match(
'/'.preg_quote(
substr( $big_chunk, 0, 20*1024 ) // 1st 20k chars
)
.'.*?'.
preg_quote(
substr( $big_chunk, -5 ) // last 5
)
.'/',
$subject
)
) {
}
if ( preg_match(
$needle_of_1st_32kbytes_chunk,
$subj, $matches, $flags = 0,
$offset = 32*1024*0 // Offset -> 0
)
&& preg_match(
$needle_of_2nd_32kbytes_chunk,
$subj, $matches, $flags = 0,
$offset = 32*1024*1 // Offset -> 32k
)
) {
}
?>
你明白了吗。
尽管这个答案有点晚,我希望它仍然能够帮助那些遇到这个问题但没有好的解释的人。