Java – 在代码中查找注释的正则表达式

这次Java 很有趣 。 我想编写一个程序,从标准输入读取代码(例如,逐行),如:

// some comment class Main { /* blah */ // /* foo foo(); // foo */ foo2(); /* // foo2 */ } 

查找其中的所有注释并将其删除。 我正在尝试使用正则表达式,现在我做了类似这样的事情:

 private static String ParseCode(String pCode) { String MyCommentsRegex = "(?://.*)|(/\\*(?:.|[\\n\\r])*?\\*/)"; return pCode.replaceAll(MyCommentsRegex, " "); } 

但它似乎不适用于所有情况,例如:

 System.out.print("We can use /* comments */ inside a string of course, but it shouldn't start a comment"); 

任何与正则表达式不同的建议或想法? 提前致谢。

你可能已经放弃了这个,但我对这个问题很感兴趣。

我相信这是部分解决方案……

原生正则表达式:

 //.*|("(?:\\[^"]|\\"|.)*?")|(?s)/\*.*?\*/ 

在Java中:

 String clean = original.replaceAll( "//.*|(\"(?:\\\\[^\"]|\\\\\"|.)*?\")|(?s)/\\*.*?\\*/", "$1 " ); 

这似乎可以正确处理嵌入在字符串中的注释以及字符串中正确的转义引号。 我向它扔了一些东西来检查,但并非详尽无遗。

有一个折衷方案是代码中的所有“”块都会以它们之后的空格结束。 考虑到需要干净地处理,保持这种简单并解决该问题将非常困难:

 int/* some comment */foo = 5; 

一个简单的Matcher.find / appendReplacement循环可以在替换为空格之前有条件地检查group(1),并且只能是少数几行代码。 可能比完整的解析器更简单。 (如果有人有兴趣,我也可以添加matcher循环。)

最后一个例子我认为没问题:

 /* we comment out some code System.out.print("We can use */ inside a string of course"); we end the comment */ 

…因为注释实际上以"We can use */ 。此代码无法编译结束。

但我有另一个有问题的案例:

 int/*comment*/foo=3; 

您的模式将转换为:

 intfoo=3; 

…什么是无效代码。 所以最好用" "而不是""替换你的评论。

我认为使用正则表达式的100%正确解决方案要么是不人道的,要么是不可能的(考虑到逃逸等)。

我相信最好的选择是使用ANTLR-我相信他们甚至提供了你可以使用的Java语法。

我最终得到了这个解决方案。

 public class CommentsFun { static List commentMatches = new ArrayList(); public static void main(String[] args) { Pattern commentsPattern = Pattern.compile("(//.*?$)|(/\\*.*?\\*/)", Pattern.MULTILINE | Pattern.DOTALL); Pattern stringsPattern = Pattern.compile("(\".*?(? commentsToRemove = new ArrayList(); Matcher stringsMatcher = stringsPattern.matcher(text); while (stringsMatcher.find()) { for (Match comment : commentMatches) { if (comment.start > stringsMatcher.start() && comment.start < stringsMatcher.end()) commentsToRemove.add(comment); } } for (Match comment : commentsToRemove) commentMatches.remove(comment); for (Match comment : commentMatches) text = text.replace(comment.text, " "); System.out.println(text); } //Single-line // "String? Nope" /* * "This is not String either" */ //Complex */ ///*More complex*/ /*Single line, but */ String moreFun = " /* comment? doubt that */"; String evenMoreFun = " // comment? doubt that "; static class Match { int start; String text; } } 

另一种方法是使用一些支持AST解析的库,例如org.eclipse.jdt.core具有你需要的所有API以及更多。 但那只是一个选择:)