当前位置: 首页 > news >正文

程序代码行数统计脚本

大多数逻辑是本地AI生成的,自己进行了组合和微调

<?php /** * PHP 程序文件有效代码行数统计工具 code_counter.php * * 统计规则: * 1. 忽略行首的空白字符。 * 2. 处理多行注释 \/* ... *\/,遇到 \/* 则进入状态,直到遇到 *\/ 才会退出状态。 * 3. 处理单行注释 //,在非多行注释状态下,以 // 开头的行不计入代码。 * 4. 整行全是空白字符的行不计入代码。 * */ define('DEBUG_MODE', false); function code_counter(string $filePath) { // 状态变量:追踪是否处于多行注释块内部 $inMultilineComment = false; $validCodeLines = 0; $fp = fopen($filePath, 'rb'); if (!$fp) die("Error: Could not read the file $filePath.\n"); $lineNo = 0; while ($line = fgets($fp)) { $lineNo++; $trimmedLine = trim($line); // 移除两边空白 if ($trimmedLine === '') { if (DEBUG_MODE) echo "00: line $lineNo is empty line\n"; continue; // 空白行不计入 } // 是否遇到块注释结束。 这里仅考虑同一行只会出现注释符结束标记,后续没有代码和注释, // 最多错误计数1行而已。开始标记也只进行简单处理 if ($inMultilineComment && strpos($trimmedLine, '*/') !== false) { $inMultilineComment = false; if (DEBUG_MODE) echo "*/: line $lineNo is comment end line\n"; continue; } if (!$inMultilineComment && strpos($trimmedLine, '/*') !== false) { $inMultilineComment = true; if (DEBUG_MODE) echo "/*: line $lineNo is comment start line\n"; continue; } // 块注释内部的行不计入 if ($inMultilineComment) { if (DEBUG_MODE) echo "**: line $lineNo is the line inside a comment block\n"; continue; } // 单行注释不计入 if (str_starts_with($trimmedLine, '//')) { if (DEBUG_MODE) echo "//: line $lineNo is single comment line\n"; continue; } // 是有效行 $validCodeLines++; } fclose($fp); if (DEBUG_MODE) printf("Total %4d, valid %4d -> %s\n", $lineNo, $validCodeLines, $filePath); return $validCodeLines; } /** * * 功能: 遍历指定目录及其所有子目录,统计指定后缀的文件某种信息,我们是代码行数 * * 使用方法: php code_counter.php <目录路径> <逗号分隔的后缀列表> * * 示例: php code_counter.php /var/www/project php,html,css */ // 检查命令行参数 if ($argc !== 3) { echo "Usage: php $argv[0] <directory_path> <comma_separated_extensions>\n"; echo "Example: php $argv[0] ./my_project php,css,js\n"; exit(1); } $directoryPath = $argv[1]; $extensionsInput = $argv[2]; // 1. 校验目录是否存在且可读 if (!is_dir($directoryPath)) { echo "Error: Directory '$directoryPath' does not exist or is not a directory.\n"; exit(1); } // 2. 解析后缀列表 // 将逗号分隔的字符串转换为数组,并转换为小写,方便匹配 $allowedExtensions = array_map('trim', explode(',', $extensionsInput)); $allowedExtensions = array_map('strtolower', $allowedExtensions); // 3. 使用递归迭代器遍历目录 try { // RecursiveDirectoryIterator 遍历目录,RecursiveIteratorIterator 遍历目录树 $dirIterator = new RecursiveDirectoryIterator($directoryPath); $iterator = new RecursiveIteratorIterator($dirIterator); $foundFiles = 0; foreach ($iterator as $fileInfo) { // 仅处理文件,跳过目录 if ($fileInfo->isFile()) { $fileName = $fileInfo->getRealPath(); // https://www.php.net/manual/en/splfileinfo.getrealpath.php $fileExtension = strtolower($fileInfo->getExtension()); // 扩展名,不带点 // 检查文件扩展名是否在允许的列表中 if (in_array($fileExtension, $allowedExtensions)) { $validCodeLines = code_counter($fileName); echo $fileName. ",". $validCodeLines. "\n"; } } } } catch (UnexpectedValueException $e) { echo "Error accessing directory: " . $e->getMessage() . "\n"; } ?>
http://www.jsqmd.com/news/1112768/

相关文章:

  • 【Linux】章11 管理网络安全(RH134知识点问答题)
  • 理论都会,实战就废?7个分析模板,帮你打通任督二脉
  • 机器学习模型生产部署:从服务化到漂移监控的四层实战体系
  • 三进制太玄经·八十一首(坤至乾·每行一卦·配原文)
  • 从Hello World到部署上线,ChatGPT辅助编程全流程拆解,含17个避坑清单与3个私藏Prompt模板
  • 2026年企业安全基建的误区、重构与最优解
  • 从0开始学AI Agent:设计一个coding agent,Java佬必看
  • 郴州火锅排行榜|客观实测,理性就餐选型指南
  • 开源AI创作工作台infinite-canvas:一站式可视化无限画布部署与使用指南
  • AutoRaise终极指南:3分钟实现macOS鼠标悬停自动激活窗口,提升300%工作效率
  • 推算术:中华传统阴阳数理思维的文化探析
  • AOT 的使用以及 .NET 与 Go 互相调用
  • 从对话到行动:基于LangChain构建AI Agent的实战指南
  • ASP.NET Core Kestrel服务器HTTPS配置与传输安全加固实战指南
  • apate文件伪装工具:如何在3秒内绕过格式限制的完整指南
  • 一文看懂PCIe 20年狂飙史与硬核避坑指南
  • 图片分类与对象识别
  • Orca ADE:多智能体并行编程,突破AI开发效率瓶颈
  • Java毕业设计-基于 SpringBoot 的社区康养管理系统的设计与实现 基于 SpringBoot 的社区老人康养综合中心管理系统(源码+LW+部署文档+全bao+远程调试+代码讲解等)
  • LeetCode 264.丑数II
  • 第一出:record 类型
  • 从确定性代码到非确定性Agent:AI Agent工程的核心挑战与实战指南
  • react hook 原理
  • 2026年健康早餐新选择:揭秘最受欢迎的苦荞片品牌
  • AI Agent赋能外贸客户开发:从电梯行业实战看自动化精准获客
  • IDA Pro Linux二进制逆向分析:从静态分析到动态调试实战指南
  • Z-Blog vs WordPress 多语言方案深度对比:中小站出海到底该选谁?
  • 2026最新8款vibe coding工具平替深度实测合集
  • 避开Claude Code七大深坑,AI编程代理效率提升50%
  • SpringBoot整合Redis实战:从配置到分布式锁