Java中如何批量执行replaceAll移除代码注释?
移除Java代码注释的解决方案
我太懂这种状态不佳时卡壳的感觉了!先看看你当前代码的核心问题:你每次调用replaceAll都是基于原始的input字符串操作,而不是在前一次替换的结果上继续处理,所以三个替换并没有真正“同时生效”——比如change2只是删掉了原始行里的*/,但之前的/*还留在内容里,这肯定不是你想要的效果。
快速修复:链式调用replaceAll
最简单的解决办法就是把三个replaceAll链式调用,让每一步都在前一步处理后的字符串上继续操作,同时优化正则表达式,确保彻底移除注释内容(而不只是注释符号):
import java.io.*; import java.util.*; public class Ex13Ch6 { public static void main(String args[]) throws FileNotFoundException { File file = new File("killComment.txt"); Scanner s = new Scanner(file); stripComments(s); } public static void stripComments(Scanner s) { while(s.hasNext()) { String input = s.nextLine(); // 链式替换:先清块注释符号,再清除行注释(从//到行尾的所有内容) String result = input.replaceAll("/\\*", "") .replaceAll("\\*/", "") .replaceAll("//.*", ""); System.out.println(result); } } }
这里的//.*是关键——它会匹配从//开始到行尾的所有内容,能彻底删掉行注释,而不是只删掉//符号。不过这个版本有个局限:处理不了跨行的块注释(比如/*在第一行,*/在第三行),也会误删字符串里的注释符号(比如String str = "// 这不是注释";里的//)。
更严谨的正则方案(支持跨行块注释)
如果要覆盖大部分常见场景(暂时忽略字符串里的注释符号),可以先把文件内容全部读入,再用更完善的正则处理:
import java.io.*; import java.util.*; public class Ex13Ch6 { public static void main(String args[]) throws FileNotFoundException { File file = new File("killComment.txt"); Scanner s = new Scanner(file); stripComments(s); } public static void stripComments(Scanner s) { // 先把所有内容读入字符串,处理跨行块注释 StringBuilder fullContent = new StringBuilder(); while(s.hasNext()) { fullContent.append(s.nextLine()).append("\n"); } // 移除块注释(包括跨行) String result = fullContent.toString().replaceAll("/\\*[^*]*\\*+(?:[^/*][^*]*\\*+)*/", ""); // 移除行注释 result = result.replaceAll("//.*", ""); // 清理替换后多余的空行(可选) result = result.replaceAll("(?m)^\\s*$\\n?", ""); System.out.println(result); } }
这个正则的逻辑:
/\\*[^*]*\\*+(?:[^/*][^*]*\\*+)*/:精准匹配标准块注释,包括跨行的情况//.*:匹配所有行注释- 最后一步的正则用来删除替换后留下的空行,让输出更整洁
不用正则的可靠方案:状态机
如果要处理更复杂的边缘情况(比如字符串、字符字面量里的注释符号),状态机是更稳妥的选择。核心思路是跟踪当前是否处于块注释状态,逐字符处理内容:
import java.io.*; import java.util.*; public class Ex13Ch6 { public static void main(String args[]) throws FileNotFoundException { File file = new File("killComment.txt"); Scanner s = new Scanner(file); stripComments(s); } public static void stripComments(Scanner s) { boolean inBlockComment = false; while(s.hasNextLine()) { String line = s.nextLine(); StringBuilder processedLine = new StringBuilder(); int i = 0; while (i < line.length()) { if (inBlockComment) { // 寻找块注释结束符 if (i < line.length() - 1 && line.charAt(i) == '*' && line.charAt(i+1) == '/') { inBlockComment = false; i += 2; // 跳过*/ } else { i++; } } else { // 寻找块注释开始符 if (i < line.length() - 1 && line.charAt(i) == '/' && line.charAt(i+1) == '*') { inBlockComment = true; i += 2; // 跳过/* } // 寻找行注释 else if (i < line.length() - 1 && line.charAt(i) == '/' && line.charAt(i+1) == '/') { break; // 行注释后面的内容直接忽略 } // 正常字符保留 else { processedLine.append(line.charAt(i)); i++; } } } // 只输出非空的行(避免空行刷屏) if (!processedLine.toString().trim().isEmpty()) { System.out.println(processedLine); } } } }
这个方法能完美处理跨行块注释,还不会误删字符串里的注释符号,是生产环境中更可靠的选择。
内容的提问来源于stack exchange,提问作者Bill Bumbleton
相关产品推荐
相关产品推荐

