PHP多文件函数起止行号定位:无法匹配函数结束行
解决PHP函数结束行号定位问题
我明白你现在的困境——要在带行号的PHP代码字符串里找到函数的结束行,尤其是函数内部还有嵌套花括号的情况,普通的字符串查找或者简单正则根本搞不定。你的当前方法把正则和普通字符串拼接在一起传给get_string_between,但这个函数根本不支持正则匹配,这就是为什么你拿不到结果的原因。
正确的思路:用栈跟踪花括号层级
PHP函数的结束位置是与函数开头的{匹配的那个},而函数内部可能有嵌套的代码块(比如你的示例里Line15的{),这时候必须用栈来记录花括号的层级:
- 从函数起始的
{开始,每遇到一个{就把它压入栈 - 每遇到一个
}就从栈里弹出一个元素 - 当栈为空的时候,当前的
}就是函数的结束标记,对应的行号就是你要找的结果
具体实现代码
下面是针对你的场景写的完整代码,结合你的示例字符串测试:
<?php // 你的示例代码字符串 $string = "Line11 blah blah blah Line12 function doSomething ( \$foo, \$fab ) Line13 { Line14 ... Line15 { Line16 ... Line18 ... Line19 ... Line21 if (... ) Line22 ... ( ... ); Line23 break; Line24 } Line25 die ( ... ); Line26 } Line27 Blah Blah Blah"; // 已知的函数信息 $functionName = 'doSomething'; $startLine = 12; // 把字符串按行分割成数组 $lines = explode("\n", $string); $braceStack = []; $endLine = null; // 遍历每一行,找到函数结束位置 foreach ($lines as $line) { // 提取行号(从"LineXXX"里取出数字) preg_match('/^Line(\d+)/', $line, $matches); if (!isset($matches[1])) continue; $currentLineNum = (int)$matches[1]; // 跳过起始行之前的内容 if ($currentLineNum < $startLine) continue; // 找到函数定义行后,开始处理后续行的花括号 if ($currentLineNum === $startLine) { // 下一行才是函数的起始{,所以继续遍历 continue; } // 检查当前行的内容里的{和} $lineContent = substr($line, strpos($line, ' ') + 1); // 去掉开头的LineXXX部分 $chars = str_split($lineContent); foreach ($chars as $char) { if ($char === '{') { array_push($braceStack, '{'); } elseif ($char === '}') { if (!empty($braceStack)) { array_pop($braceStack); // 当栈为空时,说明找到了匹配函数起始{的结束} if (empty($braceStack)) { $endLine = $currentLineNum; break 2; // 跳出两层循环 } } } } } // 输出结果 echo "函数结束行号:" . $endLine; // 输出26 ?>
代码说明
- 行分割与行号提取:先把字符串按换行分割成每行,然后用正则提取每行的行号
- 栈跟踪逻辑:从函数起始行的下一行开始,逐字符检查花括号,用栈记录层级。当栈被清空时,当前行就是函数的结束行
- 处理嵌套花括号:不管函数内部有多少层嵌套的
{},栈都会准确跟踪,只有当匹配到函数最外层的}时才会停止
这个方法比你之前的字符串查找靠谱多了,完美解决嵌套代码块的问题。
内容的提问来源于stack exchange,提问作者Carl M
相关产品推荐
相关产品推荐

