2011-03-09 162 views

回答

2

试试这个:

public class Test { 

    // comment 1 

    /* 
    comment 2 
    // no line comment 
    */ 

    char c = '"'; // comment 3, " is not the start of a string literal! 

    String s = "/* no comment */ ... /*"; 

    String t = "*/ also // not a comment"; 

    private static String getContentsOf(String fileName) throws FileNotFoundException { 
     Scanner scan = new Scanner(new File(fileName)); 
     StringBuilder b = new StringBuilder(); 
     while(scan.hasNextLine()) { 
      b.append(scan.nextLine()).append("\n"); 
     } 
     return b.toString(); 
    } 

    public static void main(String[] args) throws FileNotFoundException { 
     String anyChar = "[\\s\\S]"; 
     String singleLineComment = "//[^\r\n]*"; 
     String multiLineComment = "/\\*" + anyChar + "*?\\*/"; 
     String stringLiteral = "\"(?:\\\\.|[^\"\r\n\\\\])*\""; 
     String charLiteral = "'(?:\\\\.|[^'\r\n\\\\])+'"; 

     String regex = String.format("(%s)|(%s)|(%s)|(%s)|(%s)", 
       singleLineComment, // group 1 
       multiLineComment, // group 2 
       stringLiteral,  // group 3 
       charLiteral,  // group 4 
       anyChar);   // group 5 

     Matcher m = Pattern.compile(regex).matcher(getContentsOf("Test.java")); 

     while(m.find()) { 
      String matched = m.group(); 
      if(m.group(1) != null || m.group(2) != null) { 
       System.out.println("matched = " + matched); 
      } 
     } 
    } 
} 

它打印:

matched = // comment 1 
matched = /* 
    comment 2 
    // no line comment 
    */ 
matched = // group 1 
matched = // group 2 
matched = // group 3 
matched = // group 4 
matched = // group 5 

或者,也许更健壮的解决方案是使用一个小解析器或解析器生成器。 ANTLR有一个很好的选择,只定义一部分语言的语法,而忽略其余部分。我在this previous Q&A中证明了这一点。缺点是你需要学习一些ANTLR ...

+0

不错的一个!但是'\ u002F * * /'呢? :P – 2011-03-09 10:18:26

+0

@Alan:糟糕的运动! :)我会把它作为读者的练习。 – 2011-03-09 10:23:41

3

虽然它可以用正则表达式解决,但解析任何类型的结构化标记时,最好的解决方案是使用实际理解所用语言的解析器。

在这种情况下:使用Java grammar的Java源解析器,如javaparserANTLR的定制解决方案。