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

Java-在代码中查找注释的正则表达式,java,regex,search,comments,Java,Regex,Search,Comments,这次使用Java有点乐趣。我想编写一个程序,从标准输入(例如,逐行)读取代码,如: 查找其中的所有注释并将其删除。我正在尝试使用正则表达式,目前我做了如下工作: private static String ParseCode(String pCode) { String MyCommentsRegex = "(?://.*)|(/\\*(?:.|[\\n\\r])*?\\*/)"; return pCode.replaceAll(MyCommentsRegex, " "); }

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

查找其中的所有注释并将其删除。我正在尝试使用正则表达式,目前我做了如下工作:

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");
有什么与regex不同的建议或想法吗?
提前感谢。

另一种选择是使用一些支持AST解析的库,例如org.eclipse.jdt.core提供了执行此操作和其他操作所需的所有API。但这只是一种选择:)

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

/* we comment out some code
System.out.print("We can use */ inside a string of course");
we end the comment */
。。。因为注释实际上以
结尾,所以我们可以使用*/
。此代码不编译

但我还有另一个问题:

int/*comment*/foo=3;
您的模式将此转换为:

intfoo=3;

…什么是无效代码。因此,最好用
替换您的注释,而不是

我认为使用正则表达式的100%正确解决方案是不人道的或不可能的(考虑到转义等)


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

您可能已经放弃了这一点,但我对这个问题很感兴趣

我相信这是一个局部解决方案

本机正则表达式:

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

String clean = original.replaceAll( "//.*|(\"(?:\\\\[^\"]|\\\\\"|.)*?\")|(?s)/\\*.*?\\*/", "$1 " );
这似乎可以正确处理字符串中嵌入的注释以及字符串中正确转义的引号

有一种折衷办法,代码中的所有“”块后面都会有空格。考虑到需要干净地处理,保持这个简单并解决这个问题将非常困难:

int/* some comment */foo = 5;

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

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

public class CommentsFun {
    static List<Match> commentMatches = new ArrayList<Match>();

    public static void main(String[] args) {
        Pattern commentsPattern = Pattern.compile("(//.*?$)|(/\\*.*?\\*/)", Pattern.MULTILINE | Pattern.DOTALL);
        Pattern stringsPattern = Pattern.compile("(\".*?(?<!\\\\)\")");

        String text = getTextFromFile("src/my/test/CommentsFun.java");

        Matcher commentsMatcher = commentsPattern.matcher(text);
        while (commentsMatcher.find()) {
            Match match = new Match();
            match.start = commentsMatcher.start();
            match.text = commentsMatcher.group();
            commentMatches.add(match);
        }

        List<Match> commentsToRemove = new ArrayList<Match>();

        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;
    }
}
公共类注释fun{
静态列表commentMatches=new ArrayList();
公共静态void main(字符串[]args){
Pattern commentsPattern=Pattern.compile((//.*?$)|(/\*.*?\\*/)”,Pattern.MULTILINE | Pattern.DOTALL);

Pattern stringsPattern=Pattern.compile(“(\”*?)(?此处不允许使用它-当其中一条规则仅使用基本包时,这是一种打赌;)但无论如何,谢谢你,我得看一看。我认为你的确切例子很古怪:字符串中的关闭注释将关闭注释。但是,字符串中未包含注释的打开注释不会启动注释。是的,我的错。我试图给出一些棘手的问题,并欺骗了我自己。如果你能整合和使用,我将不胜感激你试过之后,请不要在答案中写上。我也在寻找类似的答案solution@Ravisha,我刚看到你的评论。我将查找我的代码,因为这只是一项一次性任务,如果我找到它,请将其发布在这里。@brovor..很高兴看到您的回复…提前感谢您,顺便说一句:)我不是在做代码解析器/翻译器或任何类似的东西,只是想创建一个简单的程序,它可以像上面所描述的那样工作;)@brovar-他是说没有解析器你是做不到的。注意:所谓“部分解决方案”,我的意思是我还没有想出一个失败的例子,也没有在replaceAll()中严格使用它将在“quoted”之后添加额外的空格“字符串。嗨,谢谢你的回答,我刚刚找到了。我已经用另一种方法解决了这个问题,但我回家后会试试,因为它看起来很有趣。对不起,这个正则表达式`你现在可能已经放弃了,但我对这个问题很感兴趣。我相信这是一个部分解决方案……原生正则表达式:/.*.|((?:\[^”]|\\“|.*?”)|(?s)/*.*/`matches String str=
“Calling a zip function”
;这似乎也匹配注释外的字符串。它匹配所有类型的字符串,但会将其替换为它们自己。这就是诀窍。因此它将匹配“Calling a zip function”,并将其替换为自身。它将匹配/*some comment*/并将其替换为nothing。可能在某些情况下,它不会替换代码中的注释,但不会替换字符串中的注释,但还没有人给出示例。
public class CommentsFun {
    static List<Match> commentMatches = new ArrayList<Match>();

    public static void main(String[] args) {
        Pattern commentsPattern = Pattern.compile("(//.*?$)|(/\\*.*?\\*/)", Pattern.MULTILINE | Pattern.DOTALL);
        Pattern stringsPattern = Pattern.compile("(\".*?(?<!\\\\)\")");

        String text = getTextFromFile("src/my/test/CommentsFun.java");

        Matcher commentsMatcher = commentsPattern.matcher(text);
        while (commentsMatcher.find()) {
            Match match = new Match();
            match.start = commentsMatcher.start();
            match.text = commentsMatcher.group();
            commentMatches.add(match);
        }

        List<Match> commentsToRemove = new ArrayList<Match>();

        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;
    }
}