Найти несколько комментариев 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 /* */";