如何用正则表达式提取PHP类定义前后的use语句?
如何区分提取PHP类定义前后的use语句?
现有压缩后无换行的代码示例:
use namespace; class name impl... { use Trait; },需求是提取类定义之前或之后的use语句。实际代码文件中可能存在多个分散的use(前后均有)、中间夹杂其他内容,目前能提取全部use,但需要分别提取类定义前后的use,请问该如何实现?
这个问题核心就是先把代码拆分成类定义前和**类定义后(类主体)**两个独立区域,再分别提取对应区域的use语句——毕竟全局匹配没法区分位置对吧?我给你捋个可行的方案:
步骤1:精准拆分代码为类前/类后两段
首先得找到类定义的起始位置,考虑到PHP类可能带abstract或final修饰符,用正则就能定位到类的开头:
/(abstract|final)?\s*class\s+\w+/
找到匹配结果的起始位置后,就能把原字符串切成两段:
- 类前部分:从字符串开头到匹配结果的起始位置
- 类后部分:从匹配结果的结束位置到字符串末尾(也就是类的大括号内部内容)
步骤2:分别提取两段中的use语句
接下来针对两个区域,用专门匹配use语句的正则来提取。这个正则要覆盖命名空间(含反斜杠)、可选的别名(as 别名)语法:
/use\s+[\w\\]+(?:\s+as\s+\w+)?;/g
加上全局匹配修饰符,就能把对应区域的所有use语句都捞出来。
完整PHP示例代码
假设你拿到的压缩代码是这样的:
$code = "use App\Helpers;use App\Models\User;final class Post implements JsonSerializable { use SoftDeletes; use HasFactory; }";
实现区分提取的代码如下:
// 1. 定位第一个类定义的起始位置 $classPattern = '/(abstract|final)?\s*class\s+\w+/'; preg_match($classPattern, $code, $matches, PREG_OFFSET_CAPTURE); $classStartPos = $matches[0][1]; $classMatchLength = strlen($matches[0][0]); // 拆分出类前和类后的代码段 $beforeClass = substr($code, 0, $classStartPos); $afterClass = substr($code, $classStartPos + $classMatchLength); // 2. 定义匹配use语句的正则 $usePattern = '/use\s+[\w\\]+(?:\s+as\s+\w+)?;/'; // 提取类前的所有use语句 preg_match_all($usePattern, $beforeClass, $beforeUses); echo "类前的use语句:\n" . implode("\n", $beforeUses[0]) . "\n\n"; // 提取类后的所有use语句 preg_match_all($usePattern, $afterClass, $afterUses); echo "类后的use语句:\n" . implode("\n", $afterUses[0]);
运行后会输出:
类前的use语句: use App\Helpers; use App\Models\User; 类后的use语句: use SoftDeletes; use HasFactory;
额外注意点
- 如果你的代码里有多个类,上面的示例只会处理第一个出现的类。如果要处理所有类,只需要循环调用
preg_match_all找到所有类的位置,逐个拆分处理即可。 - 如果代码里存在字符串或注释中的
class关键字(比如$str = "class test";),上面的正则会误匹配。但如果你的代码已经预处理过(移除了注释、换行),这个问题基本可以忽略;如果需要更严谨,可以先做一次字符串和注释的过滤,再进行类定位。
内容的提问来源于stack exchange,提问作者Daniel B
相关产品推荐
相关产品推荐

