Как найти (* комментарии *), используя регулярное выражение Java? - PullRequest
1 голос
/ 27 марта 2011

Я не знаю, как работать с '(', ')' и '*', которые могут быть в комментариях.Комментарии многострочные.

Ответы [ 3 ]

6 голосов
/ 27 марта 2011

Простой шаблон для обработки:

\(\*(.*?)\*\)

Пример: http://www.rubular.com/r/afqLCDssIx

Возможно, вы также захотите установить однострочный флаг, (?s)\(\*(.*?)\*\)

Обратите внимание, что это не обрабатывает такие случаи, как (* в строках или другие странные комбинации.Лучше всего использовать синтаксический анализатор, например ANTLR , который уже содержит грамматику Pascal ( прямая ссылка ).

4 голосов
/ 02 марта 2012

Если вы хотите найти самый внутренний вложенный комментарий для / * * / example

/* 
/*
comment1
/*
comment2
*/
*/
*/

, регулярное выражение будет

\/\*[^/*]*(?:(?!\/\*|\*\/)[/*][^/*]*)*\*\/

, это найдет

/*
comment2
*/
1 голос
/ 28 марта 2011

Что касается обработки вложенных комментариев, хотя верно то, что вы не можете использовать регулярное выражение Java для сопоставления с крайним комментарием, вы можете создать комментарий, который будет соответствовать самый внутренний комментарий (с некоторыми заметными исключениями - см. предостережения ниже). (Обратите внимание, что выражение: \(\*(.*?)\*\) НЕ будет работать в этом случае, так как оно не соответствует внутреннему комментарию.) Ниже приведена протестированная Java-программа, которая использует (строго прокомментированное) регулярное выражение, которое соответствует только самым внутренним комментариям, и применяет это итеративно, чтобы правильно удалить вложенные комментарии:

public class TEST {
    public static void main(String[] args) {
        String subjectString = "out1 (* c1 *) out2 (* c2 (* c3 *) c2 *) out3";
        String regex = "" +
            "# Match an innermost pascal '(*...*)' style comment.\n" +
            "\\(\\*      # Comment opening literal delimiter.\n" +
            "[^(*]*      # {normal*} Zero or more non'(', non-'*'.\n" +
            "(?:         # Begin {(special normal*)*} construct.\n" +
            "  (?!       # If we are not at the start of either...\n" +
            "    \\(\\*  # a nested comment\n" +
            "  | \\*\\)  # or the end of this comment,\n" +
            "  ) [(*]    # then ok to match a '(' or '*'.\n" +
            "  [^(*]*    # more {normal*}.\n" +
            ")*          # end {(special normal*)*} construct.\n" +
            "\\*\\)      # Comment closing literal delimiter.";
        String resultString = null;
        java.util.regex.Pattern p = java.util.regex.Pattern.compile(
                    regex,
                    java.util.regex.Pattern.COMMENTS);
        java.util.regex.Matcher m = p.matcher(subjectString);
        while (m.find())
        { // Iterate until there are no more "(* comments *)".
            resultString = m.replaceAll("");
            m = p.matcher(resultString);
        }
        System.out.println(resultString);
    }
}

Вот краткая версия регулярного выражения (в собственном формате регулярного выражения):

\(\*[^(*]*(?:(?!\(\*|\*\))[(*][^(*]*)*\*\)

Обратите внимание, что это регулярное выражение реализует эффективную технику Джеффри Фридла "Развертывание цикла" и довольно быстро. (См .: Освоение регулярных выражений (3-е издание) ).

Предостережения: Это, безусловно, НЕ будет работать правильно, если в строковом литерале присутствует какой-либо разделитель комментариев (т.е. (* или *)) и, следовательно, НЕ должен использоваться для общего анализа. Но такое регулярное выражение удобно использовать время от времени - например, для быстрого и грязного поиска в редакторе.

См. Также мой ответ на аналогичный вопрос для кого-то, кто хочет обрабатывать вложенные комментарии в стиле C.

...