Учитывая следующий пример кода, существует ли регулярное выражение, которое захватило бы все определенные символы, исключив те, которые были закомментированы?
...
#define SYMBOL_1 // Match 1, 1 group
#undef SYMBOL_2 // Match 2, 1 group
#pragma warning disable 649
// #undef NO_MATCH
// #undef !NO_MATCH
#if(SYMBOL_3 && SYMBOL_4) // Match 3, 2 groups
#if SYMBOL_3 && SYMBOL_4 // Match 4, 2 groups
#elif SYMBOL_3 // Match 5, 1 group
#elif !SYMBOL_3 // Match 6, 1 group
#if (SYMBOL_1 && SYMBOL_2) || !SYMBOL_3 || SYMBOL_4 // Match 7, 4 groups
#elif SYMBOL_1 // Match 8, 1 group
#elif !SYMBOL_2 // Match 9, 1 group
#if (SYMBOL_1&&SYMBOL_2) || !SYMBOL_3// || NO_MATCH // Match 10, 3 groups
#if (SYMBOL_1&&!SYMBOL_2) || !SYMBOL_3 //|| NO_MATCH // Match 11, 3 groups
...
Я пробовал ряд вещей, но я ' м не совсем там. Следующее выражение фиксирует первый символ в каждой совпадающей строке (включены глобальные и многострочные параметры):
^[\t ]*#(?>if|elif|define|undef)(?> |\t|\(|\)|!|&|\|)*(\w*)
Где:
^[\t ]*#(?>if|elif|define|undef)
определяет строки, начинающиеся с #define
, #undef
, #if
и #elif
, которые не закомментированы. Предшествующие пробелы и все другие директивы препроцессора, такие как #pragma
, игнорируются. (?: |\t|\(|\)|!|&|\|)*
не захватывает, но разрешает определенные символы (space
, tab
, (
, )
, !
, &
и |
) перед символом. - и, наконец,
(\w*)
захватывает символ как группу. Все символы "SYMBOL_ #" захватываются, а символы "NO_MATCH" не связаны с предшествующими знаками комментария.
regex101 fiddle
Текущие результаты:
- Соответствие 1> Группа 1: "SYMBOL_1"
- Соответствие 2> Группа 1: "SYMBOL_2"
- Соответствие 3> Группа 1: "SYMBOL_3", но есть нет Группа 2, содержащая "SYMBOL_4".
- ... и так далее ...
Соответствия 3, 4, 7, 10 и 11 должны иметь несколько групп.
Осталось только повторить вторую (не захватывающую) и третью (захватывающую) части выражения до конца строки. Вот на чем я застрял. В настоящее время выполнено 11 совпадений, но захвачено только 11 групп. Групп должно быть 20.
Я пробовал просто дублировать эти части несколько раз, и это работает, но в результате получается очень длинное выражение и много пустых групп совпадений.
Например , ^[\t ]*#(?>if|elif|define|undef)(?> |\t|\(|\)|!|&|\|)*(\w*)(?> |\t|\(|\)|!|&|\|)*(\w*)(?> |\t|\(|\)|!|&|\|)*(\w*)(?> |\t|\(|\)|!|&|\|)*(\w*)(?> |\t|\(|\)|!|&|\|)*(\w*)(?> |\t|\(|\)|!|&|\|)*(\w*)
захватывает до шести символов за одно совпадение, однако большинство групп пусты, поскольку в каждой строке есть только один символ. Кроме того, в данной строке может быть более шести символов, и я хотел бы захватить их все.
Есть ли более чистый способ повторить (?> |\t|\(|\)|!|&|\|)*(\w*)
до конца строки, чтобы он захватывает все символы?
Я пробовал вложить эти части выражения в другую группу, чтобы можно было применить «множественный» квантификатор, но это, похоже, не помогло. Вероятно, мне что-то не хватает.
Это вопрос с регулярным выражением, но я добавил тег C#, поскольку я использую регулярное выражение в коде C#, а другие языки могут использовать другой синтаксис препроцессора, например видно здесь: Извлечение символов препроцессора из исходного кода (C / C ++)