2011-04-07 2 views
2

Я пишу простой текстовый граббер для предварительного процессора C-Style. Ввод текста (образец):Упрощение регулярного выражения - слишком много групп

#if 1 > 0 
blah 
#if defined MACRO1 
blah blah blah 
#if !defined MACRO2 
blaaaah 
#if  ! defined MACRO3 
blah? 

Я хочу, чтобы захватить текст, который приходит после каждого #if [!] defined заявления. Вывод, который я должен был бы из приведенного выше текста:

MACRO1 
MACRO2 
MACRO3 

Номера строк, необходимые для захвата здесь 3, 5 и 7. Обратите внимание, что в строке 7 получили пробелы, смешанные с закладками.

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

(?<=(?<=(?<=(?<=(?<=(?<=#if)[\s\t]+)!?)[\s\t]*)defined)[\s\t]+).*

использованные опции: Multiline + IgnoreCase

Но я уверен, что это не элегантный и лаконичный. Может ли кто-нибудь предложить лучшее выражение, пожалуйста?

PS - Я использую Expresso для проверки выражения.

+0

Это еще одна альтернатива (спасибо Весселя) : '(? <= #, если [\ s \ t] + [!]? [\ s \ t] * определено [\ s \ t] +). *' – Nayan

ответ

1

Это должно работать Учитывая, что S containes вход в ваш вопрос с линии разрывов и т.д.

foreach(var match in Regex.Matches(s, @"(?<=#if\s*!?\s*defined\s*)(?<macro_name>\w+)")) { 
    Console.WriteLine(match); 
} 

Найдет MACRO01, MACRO02 и MACRO03 в 3 захватывает

+0

Он делает! Но, пожалуйста, помогите мне в понимании того, как \ s обрабатывает вкладки также в вашем ответе? !! – Nayan

+1

Рад, что это помогло! \ s * соответствует любому пробелу, включая вкладки, * означает 0 для многих –

+0

Спасибо! Это были годы, когда я пересмотрел книги. :) Да, \ s handles \ t также. Я забыл. Dammm! =) Спасибо! – Nayan

1

Как насчет этого регулярного выражения?

#if[\s\t]+[!]?[\s\t]*defined[\s\t]*(.*) 

В backreference у вас есть MACRO1/MACRO2/MACRO3.

+0

Текст, который был захвачен, содержит всю строку, а не текст после слова 'defined'. – Nayan

+0

Но, gee, Wessel !! Вы очень близки. Это работает: '(? <= #, Если [\ s \ t] + [!]? [\ S \ t] * определено [\ s \ t] +).* ' – Nayan

+0

Я не знаю, я попробовал аналогичный ответ 2 часа назад. Это не сработало! Argh! Мне нужен кофе. – Nayan

0

Ай Nayan

я понял, что вам нужно, чтобы получить макро эталонных имен всех «#if определенных» и «#if!» Определенных директивы препроцессора, которые находятся внутри родового код текстового потока с источником. ..

я могу предложить вам, что простое регулярное выражение

^#if\s*!?\s*defined\s*(\w*).*$ 

предыдущее регулярное выражение имеет один только захват группы, определенный (\ ш *), для того, чтобы получить только имя макроса.

Группа захвата будет заполнена всеми именами макросов.

* PS: регулярное выражение должно выполняться с использованием вариантов многострочного + игнорирования. Я проверил, что один с инструментом RegExr http://gskinner.com/blog/archives/2008/03/regexr_free_onl.html *

+0

Текст, который был захвачен, содержит всю строку, а не текст после слова 'defined'. Следовательно, это потребует уточнения. – Nayan

+0

@Nayan: Текст, который соответствует IS всей строке. Но содержимое первой и единственной группы - это текст, который вы хотите извлечь. Вам действительно нужна супер-сложная задача, так что вам не нужно делать дополнительный звонок, чтобы получить значение из группы соответствия? – unholysampler

+0

Да. Plz см. Принятый ответ. Это не сложно. :) – Nayan

0

ли эту работу,

^#if(?:[ \t]*!)?[ \t]*defined[ \t]*(.*?)$ 

, без многострочного варианта?

+0

Марчелло предложил аналогичный ответ. Но это не дает мне точного результата. Пожалуйста, проверьте себя. – Nayan

Смежные вопросы