背景:
在提供源代码时,需要执行两项关键步骤:首先,移除所有注释以保证代码的简洁性和专业性;其次,彻底检查并删除任何可能存在的敏感信息,如个人身份信息、密码或密钥等,确保数据安全与隐私保护。
手动执行注释清理和敏感信息筛查存在诸多问题。首先,手动处理耗时且容易出错,特别是在大型项目中,逐一查找和移除注释及敏感信息会占用大量时间和精力,如果是通过idea的替换工具,用正则匹配表达式删除注释容易错误删除代码。其次,手动操作可能引入人为错误,例如不小心删除关键部分或遗漏某些敏感信息。
相较之下,CodeCommentCleaner 脚本提供了自动化解决方案。它采用模块化设计,支持灵活的扩展和定制,能够高效、准确地完成注释清理及敏感信息筛查,极大地节省了时间和精力,同时减少了人为错误的风险。通过正则表达式、文件过滤机制和错误处理机制,该脚本确保了操作的一致性和可靠性,提升了代码质量和安全性。
思想:
在处理代码中的特殊符号时,直接使用正则表达式去匹配 // 或者 /* 可能会影响到程序代码本身。一个更温和的方法是先将这些符号临时替换成其他不会引起冲突的字符,之后再进行注释部分的匹配工作,最后记得把原先替换掉的部分恢复原样。这样既能准确找到注释内容,又能保证原有代码结构不被破坏。
示例:
替换步骤
"/**" --> "/TaG1"
mysql:// -->mysql:TaG2
(/*([^*]|[\r\n]|(*+([^*/]|[\r\n])))**+/|[ \t]*//.*) 全局替换为 空
pom 文件 单独处理 再把 1到2 进行反向替换
测试用例
import java.util.ArrayList;
import java.util.stream.Collectors;
public class Input {
/**
* 我是 Javadoc 注释
*
* @param param1
* @param param2
*/
public static void someMethod(String param1, // 我是单行注释
String param2
// 我是单行注释 String param3,
/* 我是块注释 String param4,
String param5,
String param6 */
/* 我是块注释 String param4 */)
{
// 我是单行注释
int a = 1;
/* 我是块注释,注意我和Javadoc注释的区别,我只有一个星号 */
int b = 2;
/*
* 我是块注释
*/
int c = 3;
}
}
脚本
该软件架构采用了模块化设计理念,结合正则表达式的强大灵活性以及高效的文件过滤机制,并具备完善的错误处理机制。支持脚本执行与直接运行两种模式,确保了高度的灵活性和可扩展性,使用户能够根据具体需求便捷地调整或增强程序功能。
public class CodeCommentCleaner {
// 定义 TAG 和对应的替换规则
private static final String[][] REPLACEMENTS = {
{""/**"", "TAG1"},
{"mysql://", "TAG2"}
};
// 不仅能够匹配常见的注释格式,还能处理注释中的嵌套结构和特殊字符,确保注释被完全移除。
private static final String COMMENT_REGEX = "(/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/|[ \t]*//.*)";
public static void main(String[] args) {
// 指定要处理的目录
Path dir = Paths.get("D:\xx");
// 清除注释可以通过脚本运行
// if (args.length < 1) {
// System.out.println("Usage: java -jar CodeCommentCleaner.jar <directory>");
// return;
// }
// Path dir = Paths.get(args[0]);
try {
// 处理所有文件(排除 .git 目录、pom.xml 文件、.idea 目录和 CodeCommentCleaner.java)
Files.walk(dir)
.filter(Files::isRegularFile)
.filter(path -> !path.toString().contains(".git")) // 排除 .git 目录
.filter(path -> !path.toString().endsWith("pom.xml")) // 排除 pom.xml 文件
.filter(path -> !path.toString().contains(".idea")) // 排除 .idea 目录
.filter(path -> !path.toString().endsWith("CodeCommentCleaner.java")) // 排除脚本文件
.filter(path -> path.toString().endsWith(".java")) // 只看 .java 文件
.forEach(path -> {
try {
processFile(path);
} catch (IOException e) {
System.err.println("Error processing file: " + path + ", " + e.getMessage());
}
});
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("处理完成");
}
private static void processFile(Path filePath) throws IOException {
// 读取原始内容
String originalContent = new String(Files.readAllBytes(filePath));
// 第一步:将特殊字符串替换为 TAG
String content = applyReplacements(originalContent, REPLACEMENTS, true);
// 第二步:移除注释
content = removeComments(content);
// 第三步:将 TAG 反向替换回原始字符串
content = applyReplacements(content, REPLACEMENTS, false);
// 将处理后的内容写回文件
Files.write(filePath, content.getBytes());
}
// 移除注释的函数
private static String removeComments(String content) {
return content.replaceAll(COMMENT_REGEX, "");
}
// 应用替换的函数
private static String applyReplacements(String content, String[][] replacements, boolean forward) {
for (String[] replacement : replacements) {
if (forward) {
// 正向替换
content = content.replace(replacement[0], replacement[1]);
} else {
// 反向替换
content = content.replace(replacement[1], replacement[0]);
}
}
return content;
}
}
- 将上述代码保存为
CodeCommentCleaner.java。 - 编译该Java文件:(注意:如果该类在springboot的java下javac,运行后会出现找不到加载主类的问题,是目录结构和类路径设置不正确导致的,在 Spring Boot 项目中,编译后的类文件通常会被放置在 target/classes 或 build/classes 目录中。您需要确保编译后的 CodeCommentCleaner.class 文件在这些目录中。)
javac -encoding UTF-8 .\CodeCommentCleaner.java
- 运行编译后的类文件,并传入要处理的目录路径作为参数:
java CodeCommentCleaner xx
通过模块化的方式处理代码文件,将复杂的任务分解为多个独立的步骤,每个步骤负责特定的功能。具体流程如下:
- 读取文件内容:从指定的目录中读取所有
.java文件的内容。 - 特殊字符串替换:为了避免在移除注释时误删某些重要的字符串(如 URL、SQL 语句等),程序首先将这些字符串替换为临时的
TAG,并在处理完注释后再将TAG恢复为原始字符串。 - 注释移除:使用正则表达式匹配并移除所有类型的注释(单行注释
//和多行注释/* */)。 - 恢复原始字符串:在移除注释后,程序将之前替换的
TAG恢复为原始字符串,确保代码的完整性。 - 写回文件:将处理后的内容写回原文件。
灵活性和扩展性:
用户可以通过修改 REPLACEMENTS 数组来添加或删除特殊字符串的替换规则。例如,如果项目中使用了其他类型的 URL 或数据库连接字符串,用户可以轻松地将其添加到 REPLACEMENTS 中,确保这些字符串不会被误删。
Files.walk 和 filter 方法遍历指定目录中的所有文件,并通过多个过滤条件排除不需要处理的文件和目录(如 .git、pom.xml、.idea 等)。这种过滤机制确保了程序只处理 .java 文件,避免对其他文件进行不必要的操作。
需要去除注释的java类里面有正则可能会报错可以直接过滤掉,手动处理。添加如下代码。
.filter(path -> !path.toString().endsWith("xx.java"))
采用了流式读取和写入的方式,避免了将整个文件加载到内存中。
去除注释的正则表达式
单行注释正则
\/\/.+\n?/?
多行注释正则
\/\*[^\/]*\*\/\n?
单行加多行注释
\/\*[^\/]*\*\/|\/\/.+\n?
1. \/\*:
○ \/ 匹配一个斜杠 /。在某些情况下,斜杠需要被转义,因为它是正则表达式中的特殊字符。
○ \* 匹配一个星号 *。同样地,星号也需要被转义。
2. [^\/]*:
○ [...] 是一个字符集,表示匹配方括号内的任意一个字符。
○ [^...] 表示匹配不在方括号内的任意字符。
○ [^\/] 表示匹配除斜杠 / 之外的任何字符。
○ * 表示前面的模式可以重复零次或多次。
○ 因此,[^\/]* 表示匹配从 /* 开始到下一个 */ 之前的任何字符,但不包括斜杠 /。
3. \*\/:
○ \* 匹配一个星号 *。
○ \/ 匹配一个斜杠 /。
○ 这个部分匹配注释结束的 */。
4. \n?:
○ \n 匹配一个换行符。
○ ? 表示前面的模式可以出现零次或一次。
○ 这里,\n? 表示匹配注释后面的一个可选的换行符。