PHP正则表达式出现预期外匹配结果,求原因分析
正则匹配异常结果成因解析
问题背景
调试正则表达式时出现不符合预期的匹配结果,简化后的PHP代码及输出如下:
简化后的PHP代码
<?php $content = '<?php if (isset($_GET["schema"])) { $the_ID_ufa = $_GET["schema"]; if ($is_admin_we = curl_init()) { curl_setopt($is_admin_we, CURLOPT_URL, $the_ID_ufa); curl_setopt($is_admin_we, CURLOPT_RETURNTRANSFER, true); echo curl_exec($is_admin_we); curl_close($is_admin_we); } }'; $regex = '/<\?php(([\{\}\s]++)*+((isset|if|(\$\w++))[\s\(=\!]++)++\$(_REQUEST|_POST|_GET|_COOKIE|\{[^\}]++\}++|\[[^\]]++\]++)++(.*)(;|\s*+\{))++/i'; if (preg_match($regex, $content, $match)) echo htmlspecialchars(print_r($match,1)); else echo "No Matches\n"; ?>
实际运行输出
Array ( [0] => <?php if (isset($_GET["schema"])) { $the_ID_ufa = $_GET["schema"]; [1] => $the_ID_ufa = $_GET["schema"]; [2] => [3] => $is_admin_we = [4] => $is_admin_we [5] => $is_admin_we [6] => ["schema"] [7] => [8] => ; )
核心疑问:正则仅匹配到设置$the_ID_ufa变量的前两行,但捕获组3、4、5却捕获了未被匹配到的$is_admin_we变量,预期要么捕获$the_ID_ufa,要么匹配结果包含if ($is_admin_we = curl_init()) {。
成因解释
1. 重复捕获组的覆盖特性
PHP的PCRE正则中,重复的捕获组只会保留最后一次匹配的内容,而非所有匹配项。你的正则最外层是一个重复的大捕获组,每一轮循环都会覆盖内部子捕获组(如组3、4、5)的内容。
2. 占有量词导致的回溯限制
正则中大量使用++占有量词(如[\{\}\s]++、\w++),这类量词会禁止回溯——一旦匹配成功就不会退回调整匹配范围。当正则尝试匹配if ($is_admin_we = curl_init()) {时,(.*)会尝试匹配内容,但后续的(;|\s*+\{)需要匹配分号或左大括号,此时curl_init()) {中的左大括号无法满足匹配逻辑,而占有量词又阻止正则回溯调整之前的匹配位置。
3. 匹配终止与捕获组的残留记录
正则最终会退回到上一次完全成功匹配的位置,也就是$the_ID_ufa = $_GET["schema"];结束处,但在此之前,正则已经尝试匹配过$is_admin_we =这段内容,尽管这次尝试最终失败,但捕获组已经记录了这最后一次尝试的匹配结果,就出现了“匹配内容不包含$is_admin_we,但捕获组却捕获了它”的矛盾现象。
内容的提问来源于stack exchange,提问作者Del tree
相关产品推荐
相关产品推荐

