Удалить комментарии из исходного кода в Java - PullRequest
3 голосов
/ 05 июля 2019

Я хочу удалить все типы операторов комментариев из файла исходного кода Java. Пример:

    String str1 = "SUM 10"      /*This is a Comments */ ;   
    String str2 = "SUM 10";     //This is a Comments"  
    String str3 = "http://google.com";   /*This is a Comments*/
    String str4 = "('file:///xghsghsh.html/')";  //Comments
    String str5 = "{\"temperature\": {\"type\"}}";  //comments

Ожидаемый результат:

    String str1 = "SUM 10"; 
    String str2 = "SUM 10";  
    String str3 = "http://google.com";
    String str4 = "('file:///xghsghsh.html/')";
    String str5 = "{\"temperature\": {\"type\"}}";

Я использую следующее регулярное выражение для достижения:

    System.out.println(str1.replaceAll("[^:]//.*|/\\\\*((?!=*/)(?s:.))+\\\\*/", ""));

Это дает мне неверный результат для str4 и str5. Пожалуйста, помогите мне решить эту проблему.

Использование решений Andreas:

        final String regex = "//.*|/\\*(?s:.*?)\\*/|(\"(?:(?<!\\\\)(?:\\\\\\\\)*\\\\\"|[^\\r\\n\"])*\")";
        final String string = "    String str1 = \"SUM 10\"      /*This is a Comments */ ;   \n"
             + "    String str2 = \"SUM 10\";     //This is a Comments\"  \n"
             + "    String str3 = \"http://google.com\";   /*This is a Comments*/\n"
             + "    String str4 = \"('file:///xghsghsh.html/')\";  //Comments\n"
             + "    String str5 = \"{\"temperature\": {\"type\"}}";  //comments";
        final String subst = "$1";

        // The substituted value will be contained in the result variable
        final String result = string.replaceAll(regex,subst);

        System.out.println("Substitution result: " + result);

Работает, кроме стр5.

Ответы [ 4 ]

4 голосов
/ 05 июля 2019

Чтобы это работало, вам нужно "пропустить" строковые литералы. Вы можете сделать это, сопоставляя строковые литералы, захватывая их, чтобы их можно было сохранить.

Следующее регулярное выражение сделает это, используя $1 в качестве строки подстановки:

//.*|/\*(?s:.*?)\*/|("(?:(?<!\\)(?:\\\\)*\\"|[^\r\n"])*")

См. regex101 для демонстрации.

Тогда Java-код:

str1.replaceAll("//.*|/\\*(?s:.*?)\\*/|(\"(?:(?<!\\\\)(?:\\\\\\\\)*\\\\\"|[^\r\n\"])*\")", "$1")

Объяснение

//.*                      Match // and rest of line
|                        or
/\*(?s:.*?)\*/            Match /* and */, with any characters in-between, incl. linebreaks
|                        or
("                        Start capture group and match "
  (?:                      Start repeating group:
     (?<!\\)(?:\\\\)*\\"     Match escaped " optionally prefixed by escaped \'s
     |                      or
     [^\r\n"]                Match any character except " and linebreak
  )*                       End of repeating group
")                        Match terminating ", and end of capture group
$1                        Keep captured string literal
0 голосов
/ 05 июля 2019

{... желая прокомментировать ...}

Я рекомендую двухпроходный процесс;один основан на конце строки (//), а другой нет (/ * * /).

Мне нравится идея Павла;однако я не вижу, как он проверяет, является ли звезда следующим символом после косой черты и наоборот при закрытии.

Мне нравится идея Андреаса;однако я не смог заставить его работать с многострочными комментариями.

https://docs.oracle.com/javase/specs/jls/se12/html/jls-3.html#jls-CommentTail

0 голосов
/ 05 июля 2019

Как говорили другие, регулярное выражение здесь не очень хороший вариант.Вы можете использовать простой DFA для этой задачи.
Вот пример, который даст вам интервалы многострочных комментариев (/* */).
Вы можете сделать то же самое для однострочных комментариев.(// -- \n).

    String input = ...; //here's your input String

    //0 - source code, 
    //1 - multiple lines comment (start) (/ char)
    //2 - multiple lines comment (start) (* char)
    //3 - multiple lines comment (finish) (* char)
    //4 - multiple lines comment (finish) (/ char)
    byte state = 0; 
    int startPos = -1;
    int endPos = -1;
    for (int i = 0; i < input.length(); i++) {
        switch (state) {
        case 0:
            if (input.charAt(i) == '/') {
                   state = 1;
                   startPos = i;
            }
            break;
        case 1:
            if (input.charAt(i) == '*') {
                state = 2;
            }
            break;
        case 2:
            if (input.charAt(i) == '*') {
               state = 3;
            }
            break;
        case 3:
            if (input.charAt(i) == '/') {
                state = 0;
                endPos = i+1;

                //here you have the comment between startPos and endPos indices,
                //you can do whatever you want with it
            }

            break;
        default:
            break;
        }
    }
0 голосов
/ 05 июля 2019

Возможно, было бы лучше начать с нескольких простых выражений, шаг за шагом, таких как:

.*(\s*\/\*.*|\s*\/\/.*)

, чтобы первоначально удалить встроенные комментарии.

Демо

Тест

import java.util.regex.Matcher;
import java.util.regex.Pattern;

final String regex = "(.*)(\\s*\\/\\*.*|\\s*\\/\\/.*)";
final String string = "    String str1 = \"SUM 10\"      /*This is a Comments */ ;   \n"
     + "    String str2 = \"SUM 10\";     //This is a Comments\"  \n"
     + "    String str3 = \"http://google.com\";   /*This is a Comments*/\n"
     + "    String str4 = \"('file:///xghsghsh.html/')\";  //Comments\n"
     + "    String str5 = \"{\\\"temperature\\\": {\\\"type\\\"}}\";  //comments";
final String subst = "\\1";

final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
final Matcher matcher = pattern.matcher(string);

// The substituted value will be contained in the result variable
final String result = matcher.replaceAll(subst);

System.out.println("Substitution result: " + result);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...