Удалить все комментарии (одиночные/многострочные) и пустые строки из исходного файла

Как удалить все комментарии и пустые строки из исходного файла С#. Имейте в виду, что могут быть вложенные комментарии. Некоторые примеры:

string text = @"//not a comment"; // a comment

/* multiline
comment */ string newText = "/*not a comment*/"; // a comment

/* multiline // not a comment 
/* comment */ string anotherText = "/* not a comment */ // some text here\"// not a comment"; // a comment

У нас может быть гораздо более сложный источник, чем три приведенных выше примера. Может ли кто-нибудь предложить шаблон регулярного выражения или другой способ решить эту проблему. Я уже много раз просматривал материал через Интернет и не нашел ничего, что работает.

Ответ 1

Чтобы удалить комментарии, см. этот ответ. После этого удаление пустых строк тривиально.

Ответ 2

Вы можете использовать функцию в этом ответе:

static string StripComments(string code)
{
    var re = @"(@(?:""[^""]*"")+|""(?:[^""\n\\]+|\\.)*""|'(?:[^'\n\\]+|\\.)*')|//.*|/\*(?s:.*?)\*/";
    return Regex.Replace(code, re, "$1");
}

И затем удалите пустые строки.

Ответ 3

К сожалению, это действительно трудно сделать надежно с регулярным выражением, не имея случаев краев. Я havnt исследовал очень далеко, но вы могли бы использовать Visual Studio Language Services для анализа комментариев.

Ответ 4

Если вы хотите идентифицировать комментарии с помощью регулярных выражений, вам действительно нужно использовать регулярное выражение в качестве токенизатора. I.e., он идентифицирует и извлекает первое в строке, является ли эта вещь строковым литералом, комментарием или блоком данных, который не является ни строковым литералом, ни комментарием. Затем вы берете оставшуюся часть строки и вытаскиваете следующий токен с самого начала.

Это поможет вам решить проблемы с контекстом. Если вы просто пытаетесь найти вещи в середине строки, нет никакого хорошего способа определить, находится ли конкретный "комментарий" внутри строкового литерала или нет - на самом деле трудно определить, где строковые литералы в первую очередь, из-за таких вещей, как \". Но если вы всегда берете первое в строке, легко сказать "oh, строка начинается с ", поэтому все до следующего unescaped " больше строки". Контекст заботится о себе.

Итак, вам нужно три регулярных выражения:

  • Тот, который идентифицирует комментарий, начинающийся в начале строки (либо комментарий //, либо /*).
  • Тот, который идентифицирует строковый литерал, начинающийся в начале строки. Не забудьте проверить строки " и @"; каждый из них имеет свои крайние случаи.
  • Тот, который идентифицирует то, что не является ни одним из вышеперечисленных, и соответствует до первого, что может быть комментарием или строковым литералом.

Написание фактических шаблонов регулярных выражений остается в качестве упражнения для читателя, так как для написания и тестирования все это займет несколько часов, и я не хочу этого делать бесплатно. (усмешка) Но это, безусловно, возможно, если у вас есть хорошее понимание регулярных выражений (или у вас есть такое место, как StackOverflow, чтобы задать конкретные вопросы, когда вы застряли) и готовы написать кучу автоматических тестов для вашего кода. Однако обратите внимание на этот последний ( "что-нибудь еще" ) случай - вы хотите остановиться перед @, если он следует за ", но не для @, чтобы избежать ключевого слова для использования в качестве идентификатор.

Ответ 5

Также см. мой проект для минимизации кода С#: CSharp-Minifier

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

Ответ 6

Во-первых, вы обязательно захотите использовать RegexOptions.SingleLine при построении RegEx. Прямо сейчас вы обрабатываете отдельные строки кода.

Чтобы выразить комплимент использованию опции RegexOptions.SingleLine, вы должны убедиться, что используете начало и конец строковых якорей (^ и $ соответственно), как и для конкретных случаев, которые вы имеете, вы хотите, чтобы регулярное выражение применялось ко всей строке.

Я также рекомендую разбить условия и использовать alternation для обработки небольших случаев, создавая большее регулярное выражение из меньшего размера, упрощенные для управления выражениями.

Наконец, я знаю, что это домашнее задание, но анализ языка программирования с помощью регулярных выражений - это упражнение в бесполезности (это не практическое приложение). Это лучше для более структурированных данных. Если в будущем вы захотите сделать что-то подобное, используйте синтаксический анализатор, который построен для языка (в этом случае я настоятельно рекомендую Roslyn).

Ответ 7

Используйте мой проект, чтобы удалить большинство комментариев. https://github.com/SynAppsDevelopment/CommentRemover

Он удаляет все полнотекстовые, конечные строки и комментарии кода XML Doc с некоторыми ограничениями для сложных комментариев, объясненных в readme и источнике. Это решение С# с интерфейсом WinForms.