如何用token_get_all移除PHP中所有以_example结尾的函数
如何用token_get_all移除所有以_example结尾的PHP函数
既然你已经搞定了注释移除和起始标签处理,接下来我们只需要在token遍历过程中加入函数识别、名称判断和完整函数体跳过的逻辑就行。核心思路是跟踪几个状态:是否正在收集函数定义、是否要移除当前函数,以及函数体内大括号的嵌套深度(避免提前结束移除)。
完整实现代码
<?php // 假设你已经预处理好代码(移除注释、处理起始标签) $code = file_get_contents('your_source_code.php'); $tokens = token_get_all($code); $output = ''; $in_remove_function = false; // 是否处于要移除的函数中 $brace_depth = 0; // 函数体内大括号的嵌套深度 $collecting_function_ctx = []; // 暂存T_FUNCTION到函数名之间的内容 $waiting_for_function_name = false; // 是否正在等待获取函数名 foreach ($tokens as $token) { // 第一步:如果当前正在移除函数,处理大括号深度,直到函数体结束 if ($in_remove_function) { if (!is_array($token)) { if ($token === '{') { $brace_depth++; } elseif ($token === '}') { $brace_depth--; // 当大括号深度回到0,说明整个函数体结束 if ($brace_depth === 0) { $in_remove_function = false; } } } // 跳过所有属于要移除函数的token continue; } // 第二步:如果正在等待函数名,收集上下文直到找到函数名 if ($waiting_for_function_name) { if (is_array($token)) { list($token_id, $content) = $token; if ($token_id === T_STRING) { // 判断函数名是否以_example结尾 if (str_ends_with($content, '_example')) { // 标记要移除整个函数,清空缓冲区 $in_remove_function = true; $collecting_function_ctx = []; } else { // 保留函数,把缓冲区和函数名追加到输出 $output .= implode('', $collecting_function_ctx) . $content; } $waiting_for_function_name = false; $collecting_function_ctx = []; } else { // 收集函数修饰符(比如public、static)、空格等内容 $collecting_function_ctx[] = $content; } } else { // 收集非数组类型的token(比如空格、&符号等) $collecting_function_ctx[] = $token; } continue; } // 第三步:正常遍历token,寻找函数定义的起始标记 if (is_array($token)) { list($token_id, $content) = $token; if ($token_id === T_FUNCTION) { // 遇到函数定义,开始收集上下文,准备判断函数名 $waiting_for_function_name = true; $collecting_function_ctx[] = $content; } else { // 非函数定义的token,直接追加到输出 $output .= $content; } } else { // 单个字符的token(比如;、{等),直接追加到输出 $output .= $token; } } // 保存处理后的代码 file_put_contents('processed_code.php', $output); ?>
关键逻辑解释
- 状态跟踪:
$waiting_for_function_name:标记我们刚遇到T_FUNCTION,正在收集函数修饰符、空格等内容,直到找到函数名(T_STRING)。$in_remove_function:一旦确认函数名符合_example结尾的条件,就标记进入移除状态,跳过所有后续token直到函数体结束。
- 大括号深度处理:
函数体内可能有嵌套的大括号(比如if语句、循环),所以用$brace_depth跟踪嵌套层级,只有当深度回到0时,才说明整个函数体完全结束,退出移除状态。 - 兼容性处理:
支持带修饰符的函数(public static function demo_example())、带引用的函数(function &test_example()),因为我们会先收集这些修饰符内容,再判断函数名。
注意事项
- 如果你用的是PHP 7.x及以下版本,
str_ends_with()不可用,替换成substr($content, -8) === '_example'(_example刚好是8个字符)。 - 确保你已经正确移除了所有注释,否则注释中的内容可能干扰token识别(比如函数名旁边的注释可能被误判为函数名的一部分)。
- 建议先拿一小段测试代码验证逻辑,比如包含目标函数、普通函数、嵌套大括号的函数,确保移除逻辑准确。
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

