[英]Removing all types of comments in java file
I have a java project and i have used comments in many location in various java files in the project.我有一个 java 项目,我在项目的各种 java 文件的许多位置使用了注释。 Now i need to remove all type of comments: single line, multiple line comments.
现在我需要删除所有类型的注释:单行、多行注释。 Please provide automation for removing comments.
请提供自动化删除评论。 using tools or in eclipse etc.
使用工具或在 eclipse 等中。
Currently i am manually trying to remove all commetns目前我正在手动尝试删除所有评论
You can remove all single- or multi-line block comments (but not line comments with //
) by searching for the following regular expression in your project(s)/file(s) and replacing by $1
:您可以通过在您的项目/文件中搜索以下正则表达式并替换为
$1
来删除所有单行或多行块注释(但不是带有//
行注释):
^([^"\\r\\n]*?(?:(?<=')"[^"\\r\\n]*?|(?<!')"[^"\\r\\n]*?"[^"\\r\\n]*?)*?)(?<!/)/\\*[^\\*]*(?:\\*+[^/][^\\*]*)*?\\*+/
It's possible that you have to execute it more than once.您可能必须多次执行它。
This regular expression avoids the following pitfalls:此正则表达式避免了以下陷阱:
Code between two comments /* Comment 1 */ foo(); /* Comment 2 */
两条注释之间的代码
/* Comment 1 */ foo(); /* Comment 2 */
/* Comment 1 */ foo(); /* Comment 2 */
Line comments starting with an asterisk: //***NOTE***
以星号开头的行注释:
//***NOTE***
Comment delimiters inside string literals: stringbuilder.append("/*");
字符串文字内的注释分隔符:
stringbuilder.append("/*");
; ; also if there is a double quote inside single quotes before the comment
如果注释前的单引号内有双引号
To remove all single-line comments, search for the following regular expression in your project(s)/file(s) and replace by $1
:要删除所有单行注释,请在您的项目/文件中搜索以下正则表达式并替换为
$1
:
^([^"\\r\\n]*?(?:(?<=')"[^"\\r\\n]*?|(?<!')"[^"\\r\\n]*?"[^"\\r\\n]*?)*?)\\s*//[^\\r\\n]*
This regular expression also avoids comment delimiters inside double quotes, but does NOT check for multi-line comments, so /* // */
will be incorrectly removed.这个正则表达式也避免了双引号内的注释分隔符,但不检查多行注释,因此
/* // */
将被错误地删除。
I had to write somehting to do this a few weeks ago.几周前我不得不写一些东西来做到这一点。 This should handle all comments, nested or otherwise.
这应该处理所有注释,嵌套或其他方式。 It is long, but I haven't seen a regex version that handled nested comments properly.
它很长,但我还没有看到正确处理嵌套注释的正则表达式版本。 I didn't have to preserve javadoc, but I presume you do, so I added some code that I belive should handle that.
我不必保留 javadoc,但我认为您这样做了,所以我添加了一些我认为应该处理的代码。 I also added code to support the \\r\\n and \\r line separators.
我还添加了支持 \\r\\n 和 \\r 行分隔符的代码。 The new code is marked as such.
新代码被标记为这样。
public static String removeComments(String code) {
StringBuilder newCode = new StringBuilder();
try (StringReader sr = new StringReader(code)) {
boolean inBlockComment = false;
boolean inLineComment = false;
boolean out = true;
int prev = sr.read();
int cur;
for(cur = sr.read(); cur != -1; cur = sr.read()) {
if(inBlockComment) {
if (prev == '*' && cur == '/') {
inBlockComment = false;
out = false;
}
} else if (inLineComment) {
if (cur == '\r') { // start untested block
sr.mark(1);
int next = sr.read();
if (next != '\n') {
sr.reset();
}
inLineComment = false;
out = false; // end untested block
} else if (cur == '\n') {
inLineComment = false;
out = false;
}
} else {
if (prev == '/' && cur == '*') {
sr.mark(1); // start untested block
int next = sr.read();
if (next != '*') {
inBlockComment = true; // tested line (without rest of block)
}
sr.reset(); // end untested block
} else if (prev == '/' && cur == '/') {
inLineComment = true;
} else if (out){
newCode.append((char)prev);
} else {
out = true;
}
}
prev = cur;
}
if (prev != -1 && out && !inLineComment) {
newCode.append((char)prev);
}
} catch (IOException e) {
e.printStackTrace();
}
return newCode.toString();
}
This is an old post but this may help someone who enjoys working on command line like myself:这是一篇旧帖子,但这可能会帮助像我这样喜欢在命令行上工作的人:
The perl
one-liner below will remove all comments:下面的
perl
one-liner 将删除所有注释:
perl -0pe 's|//.*?\n|\n|g; s#/\*(.|\n)*?\*/##g;' test.java
Example:例子:
cat test.java
this is a test
/**
*This should be removed
*This should be removed
*/
this should not be removed
//this should be removed
this should not be removed
this should not be removed //this should be removed
Output:输出:
perl -0pe 's#/\*\*(.|\n)*?\*/##g; s|//.*?\n|\n|g' test.java
this is a test
this should not be removed
this should not be removed
this should not be removed
If you want get rid of multiple blank lines as well:如果您还想摆脱多个空行:
perl -0pe 's|//.*?\n|\n|g; s#/\*(.|\n)*?\*/##g; s/\n\n+/\n\n/g' test.java
this is a test
this should not be removed
this should not be removed
this should not be removed
EDIT: Corrected regex编辑:更正正则表达式
Dealing with source code is hard unless you know more on the writing of comment.除非您对注释的编写了解更多,否则处理源代码是很困难的。 In the more general case, you could have // or /* in text constants.
在更一般的情况下,您可以在文本常量中使用 // 或 /*。 So your really need to parse the file at a syntaxic level, not only lexical.
所以你真的需要在语法级别解析文件,而不仅仅是词汇。 IMHO the only bulletproof solution would be to start for example with the java parser from openjdk .
恕我直言,唯一的防弹解决方案是从openjdk的 java 解析器开始。
If you know that your comments are never deeply mixed with the code (in my exemple comments MUST be full lines), a python script could help如果您知道您的注释永远不会与代码深度混合(在我的示例中,注释必须是整行),python 脚本可能会有所帮助
multiple = False
for line in text:
stripped = line.strip()
if multiple:
if stripped.endswith('*/'):
multiple = False
continue
elif stripped.startswith('/*'):
multiple = True
elif stripped.startswith('//'):
pass
else:
print(line)
If you are using Eclipse IDE, you could make regex do the work for you.如果您使用 Eclipse IDE,您可以让正则表达式为您完成这项工作。
Open the search window (Ctrl+F), and check 'Regular Expression'.打开搜索窗口 (Ctrl+F),然后选中“正则表达式”。
Provide the expression as /\\*\\*(?s:(?!\\*/).)*\\*/
提供表达式为
/\\*\\*(?s:(?!\\*/).)*\\*/
Prasanth Bhate has explained it in Tool to remove JavaDoc comments? Prasanth Bhate 在删除 JavaDoc 注释的工具中对此进行了解释?
I made a open source library and uploaded to github, its called CommentRemover you can remove single line and multiple line Java Comments.我做了一个开源库上传到github,它叫CommentRemover,可以删除单行和多行Java注释。
It supports remove or NOT remove TODO's.它支持删除或不删除 TODO。
Also it supports JavaScript , HTML , CSS , Properties , JSP and XML Comments too.它还支持 JavaScript 、 HTML 、 CSS 、 Properties 、 JSP 和 XML 注释。
There is a little code snippet how to use it (There is 2 type usage):有一些代码片段如何使用它(有两种类型的用法):
First way InternalPath第一种方式InternalPath
public static void main(String[] args) throws CommentRemoverException {
// root dir is: /Users/user/Projects/MyProject
// example for startInternalPath
CommentRemover commentRemover = new CommentRemover.CommentRemoverBuilder()
.removeJava(true) // Remove Java file Comments....
.removeJavaScript(true) // Remove JavaScript file Comments....
.removeJSP(true) // etc.. goes like that
.removeTodos(false) // Do Not Touch Todos (leave them alone)
.removeSingleLines(true) // Remove single line type comments
.removeMultiLines(true) // Remove multiple type comments
.startInternalPath("src.main.app") // Starts from {rootDir}/src/main/app , leave it empty string when you want to start from root dir
.setExcludePackages(new String[]{"src.main.java.app.pattern"}) // Refers to {rootDir}/src/main/java/app/pattern and skips this directory
.build();
CommentProcessor commentProcessor = new CommentProcessor(commentRemover);
commentProcessor.start();
}
Second way ExternalPath第二种方式 ExternalPath
public static void main(String[] args) throws CommentRemoverException {
// example for externalInternalPath
CommentRemover commentRemover = new CommentRemover.CommentRemoverBuilder()
.removeJava(true) // Remove Java file Comments....
.removeJavaScript(true) // Remove JavaScript file Comments....
.removeJSP(true) // etc..
.removeTodos(true) // Remove todos
.removeSingleLines(false) // Do not remove single line type comments
.removeMultiLines(true) // Remove multiple type comments
.startExternalPath("/Users/user/Projects/MyOtherProject")// Give it full path for external directories
.setExcludePackages(new String[]{"src.main.java.model"}) // Refers to /Users/user/Projects/MyOtherProject/src/main/java/model and skips this directory.
.build();
CommentProcessor commentProcessor = new CommentProcessor(commentRemover);
commentProcessor.start();
}
public class TestForStrings {公共类 TestForStrings {
/**
* The main method.
*
* @param args
* the arguments
* @throws Exception
* the exception
*/
public static void main(String args[]) throws Exception {
String[] imports = new String[100];
String fileName = "Menu.java";
// This will reference one API at a time
String line = null;
try {
FileReader fileReader = new FileReader(fileName);
// Always wrap FileReader in BufferedReader.
BufferedReader bufferedReader = new BufferedReader(fileReader);
int startingOffset = 0;
// This will reference one API at a time
List<String> lines = Files.readAllLines(Paths.get(fileName),
Charset.forName("ISO-8859-1"));
// remove single line comments
for (int count = 0; count < lines.size(); count++) {
String tempString = lines.get(count);
lines.set(count, removeSingleLineComment(tempString));
}
// remove multiple lines comment
for (int count = 0; count < lines.size(); count++) {
String tempString = lines.get(count);
removeMultipleLineComment(tempString, count, lines);
}
for (int count = 0; count < lines.size(); count++) {
System.out.println(lines.get(count));
}
} catch (FileNotFoundException ex) {
System.out.println("Unable to open file '" + fileName + "'");
} catch (IOException ex) {
System.out.println("Error reading file '" + fileName + "'");
} catch (Exception e) {
}
}
/**
* Removes the multiple line comment.
*
* @param tempString
* the temp string
* @param count
* the count
* @param lines
* the lines
* @return the string
*/
private static List<String> removeMultipleLineComment(String tempString,
int count, List<String> lines) {
try {
if (tempString.contains("/**") || (tempString.contains("/*"))) {
int StartIndex = count;
while (!(lines.get(count).contains("*/") || lines.get(count)
.contains("**/"))) {
count++;
}
int endIndex = ++count;
if (StartIndex != endIndex) {
while (StartIndex != endIndex) {
lines.set(StartIndex, "");
StartIndex++;
}
}
}
} catch (Exception e) {
// Do Nothing
}
return lines;
}
/**
* Remove single line comments .
*
* @param line
* the line
* @return the string
* @throws Exception
* the exception
*/
private static String removeSingleLineComment(String line) throws Exception {
try {
if (line.contains(("//"))) {
int startIndex = line.indexOf("//");
int endIndex = line.length();
String tempoString = line.substring(startIndex, endIndex);
line = line.replace(tempoString, "");
}
if ((line.contains("/*") || line.contains("/**"))
&& (line.contains("**/") || line.contains("*/"))) {
int startIndex = line.indexOf("/**");
int endIndex = line.length();
String tempoString = line.substring(startIndex, endIndex);
line = line.replace(tempoString, "");
}
} catch (Exception e) {
// Do Nothing
}
return line;
}
} }
This is what I came up with yesterday.这是我昨天想到的。 This is actually homework I got from school so if anybody reads this and finds a bug before I turn it in, please leave a comment =)
这实际上是我从学校得到的作业,所以如果有人在我上交之前阅读了这篇文章并发现了错误,请发表评论 =)
ps.附: 'FilterState' is a enum class
'FilterState' 是一个枚举类
public static String deleteComments(String javaCode) {
FilterState state = FilterState.IN_CODE;
StringBuilder strB = new StringBuilder();
char prevC=' ';
for(int i = 0; i<javaCode.length(); i++){
char c = javaCode.charAt(i);
switch(state){
case IN_CODE:
if(c=='/')
state = FilterState.CAN_BE_COMMENT_START;
else {
if (c == '"')
state = FilterState.INSIDE_STRING;
strB.append(c);
}
break;
case CAN_BE_COMMENT_START:
if(c=='*'){
state = FilterState.IN_COMMENT_BLOCK;
}
else if(c=='/'){
state = FilterState.ON_COMMENT_LINE;
}
else {
state = FilterState.IN_CODE;
strB.append(prevC+c);
}
break;
case ON_COMMENT_LINE:
if(c=='\n' || c=='\r') {
state = FilterState.IN_CODE;
strB.append(c);
}
break;
case IN_COMMENT_BLOCK:
if(c=='*')
state=FilterState.CAN_BE_COMMENT_END;
break;
case CAN_BE_COMMENT_END:
if(c=='/')
state = FilterState.IN_CODE;
else if(c!='*')
state = FilterState.IN_COMMENT_BLOCK;
break;
case INSIDE_STRING:
if(c == '"' && prevC!='\\')
state = FilterState.IN_CODE;
strB.append(c);
break;
default:
System.out.println("unknown case");
return null;
}
prevC = c;
}
return strB.toString();
}
private static int find(String s, String t, int start) {
int ret = s.indexOf(t, start);
return ret < 0 ? Integer.MAX_VALUE : ret;
}
private static int findSkipEsc(String s, String t, int start) {
while(true) {
int ret = find(s, t, start);
if( ret == Integer.MAX_VALUE) return -1;
int esc = find(s, "\\", start);
if( esc > ret) return ret;
start += 2;
}
}
private static String removeLineCommnt(String s) {
int i, start = 0;
while (0 <= (i = find(s, "//", start))) { //Speed it up
int j = find(s, "'", start);
int k = find(s, "\"", start);
int first = min(i, min(j, k));
if (first == Integer.MAX_VALUE) return s;
if (i == first) return s.substring(0, i);
//skipp quoted string
start = first+1;
if (k == first) { // " asdas\"dasd "
start = findSkipEsc(s,"\"",start);
if (start < 0) return s;
start++;
continue;
}
//if j == first ' asda\'sasd ' --- not in JSON
start = findSkipEsc(s,"'\"'",start);
if (start < 0) return s;
start++;
}
return s;
}
static String removeLineCommnts(String s) {
if (!s.contains("//")) return s; //Speed it up
return Arrays.stream(s.split("[\\n\\r]+")).
map(Common::removeLineCommnt).
collect(Collectors.joining("\n"));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.