Найти несколько комментариев Objective C для файла в определенном формате с помощью Ruby Regex

Я пишу сценарий Ruby, который использует регулярные выражения, чтобы найти все комментарии определенного формата в файлах исходного кода Objective-C.

Формат

/* <Headline_in_caps> <#>:
    <Comment body>
**/

Я хочу зафиксировать заголовок заглавными буквами, номер и текст комментария.

С помощью приведенного ниже выражения я могу найти один комментарий в этом формате в большей части текста.

Моя проблема в том, что если в файле более одного комментария, я получаю весь текст, включая код, между первым /* и последний **/, Я не хочу, чтобы он захватывал весь текст включительно, а только то, что внутри каждого /* а также **/ ,

Тело комментария может включать все символы, кроме **/ а также */ которые оба означают конец комментария. Правильно ли я полагаю, что регулярное выражение найдет несколько совпадений с целым регулярным выражением, обрабатывая текст только один раз?

\/\*\s*([A-Z]+). (\d)\:([\w\d\D\W]+)\*{2}\//x

Разбитое на части регулярное выражение делает это:

\/\* - находит начало комментария

\s* - находит пробелы

([A-Z]+) - фиксирует заглавные буквы

.<space> - найти пробел между заглавными буквами слово и цифра

(\d) - запишите цифру

\: - найти двоеточие

([\w\W\d\D]+) - захватывает тело сообщения, которое может содержать все допустимые символы, кроме **/ или же */

\*{2}\/ - находит конец комментария

Вот образец, все с первого раза /* ко второму **/ захвачен.

/*

 HEADLINE 1:

 Comment body.

 **/

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// This text and method declaration are captured
// The regex captures from HEADLINE to the end of the comment "meddled in." inclusively.

/*
       HEADLINE 2:

       Should be captured separately and without Objective-C code meddled in. 
 **/

}

Вот пример на Rubular: http://rubular.com/r/4EoXXotzX0

я использую gsub обработать регулярное выражение в строке всего файла, запустив Ruby 1.9.3. Другая проблема, с которой я столкнулся, заключается в том, что gsub дает мне то, что игнорирует Rubular. Это регрессия или Rubular использует другой метод, который дает то, что я хочу?

В этом вопросе Regex сопоставляет несколько вхождений в файле и в строке о нескольких вхождениях, поэтому ответом является использование g для глобальной опции, которая недопустима в Ruby regex.

2 ответа

Решение

Изменить это: ([\w\W\d\D]+)
К этому: ([\w\W\d\D]+?)

Это приведет к тому, что регулярное выражение будет не жадным и остановится, как только увидит следующее закрытие **/, (Обновленный Rubular: http://rubular.com/r/Whm31AJ6Kg)

Также обратите внимание, что [\w\W\d\D] соответствует абсолютно любому символу и может быть проще записано как просто [\w\W], Вы могли бы альтернативно сопоставить тело с просто [^*\/], что также позволило бы избежать вышеуказанной проблемы сопоставления через закрытие. (Обновленный Rubular: http://rubular.com/r/2h0kGYkdVQ)

Решение:

  • Разделить всю строку с '*/' (конец комментария)
  • Если разделение возвращает только один элемент, в строке нет комментариев
  • В противном случае для каждого токена, кроме последнего, используйте RegExp %r{/\*(.*)$} (начиная с '/*' до конца токена) для захвата всего прокомментированного контента (здесь вы можете использовать более сложный RegExp для сбора большего количества данных в комментарии)

Это может быть не самое красивое решение, но оно должно делать свою работу. И это не пуленепробиваемое, если у вас есть в исходном коде Objective-C что-то вроде строки ниже, мое решение потерпит неудачу.

 char *myString = "a comment /*  */";
Другие вопросы по тегам