Регулярное выражение для соответствия файлу C #include - PullRequest
7 голосов
/ 14 сентября 2009

Мне нужна помощь, чтобы сопоставить включаемый файл C с полным путем, например:

#include <stdio.h>  -> stdio.h
#include "monkey/chicken.h" -> monkey/chicken.h

Пока что я (адаптировано из другого найденного выражения):

^\s*\#include\s+(["'<])([^"'<>/\|\b]+)*([">])

Но я застрял на этом этапе - во втором случае он не совпадает, и я не уверен, как вернуть результат совпадения, например, путь к файлу обратно в regcomp ().

Кстати, я смотрел на regexplib.com, но не могу найти ничего подходящего.

Редактировать: Да, я новичок в регулярных выражениях, использую регулярное выражение POSIX с regmatch_t и друзьями ...

Ответы [ 6 ]

7 голосов
/ 14 сентября 2009

Вот что я написал:

#include ((<[^>]+>)|("[^"]+"))

Подходит?

5 голосов
/ 14 сентября 2009

Это даст лучшие результаты:

^\s*\#include\s+["<]([^">]+)*[">]

Затем вы хотите посмотреть на первую группу захвата, когда получите совпадение.

Вы не говорите, какой язык вы используете, фактор, о котором вы упомянули regcomp (), наводит меня на мысль, что вы используете библиотеку регулярных выражений POSIX в C. Если это так, то вы хотите использовать функцию regexec используйте параметры nmatch и pmatch, чтобы получить первую группу захвата.

2 голосов
/ 14 марта 2012

Если вам нужно более точное решение, которое позволяет также оставлять комментарии перед включаемым файлом, например,

  /* ops, a comment */ /* oh, another comment */   #include  "new_header1.h" /* let's try another with an #include "old_header.h" */

есть:

^(?:\s*|\s*\/\*.*?\*\/)\s*#include\s*(?:(?:<)(?<PATH>.*?)(?:>)|(?:")(?<PATH>.*?)(?:"))
2 голосов
/ 14 сентября 2009

Вы можете попробовать это регулярное выражение:

(^\s*\#\s*include\s*<([^<>]+)>)|(^\s*\#\s*include\s*"([^"]+)")

Я предпочитаю иметь отдельное регулярное выражение для
#include <>
и
#include ""

1 голос
/ 14 сентября 2009

Не особенно хорошо протестирован, но соответствует вашим двум случаям:

^\s*#include\s+(<([^"'<>|\b]+)>|"([^"'<>|\b]+)")

Единственная проблема в том, что из-за <и> результат может быть в группе захвата 2 или 3, поэтому вы должны проверить, если 2 пусто, а затем использовать 3 ... Преимущество над некоторыми другими ответами в том, что он не будет совпадать с чем-то вроде этого: #include "bad.h> или с этим: #include

А вот пример того, как использовать regcomp & friends:

 static bool regexMatch(const std::string& sRegEx, const std::string& sSubject, std::vector<std::string> *vCaptureGroups)
 {
  regex_t re;
  int flags = REG_EXTENDED | REG_ICASE;
  int status;

  if(!vCaptureGroups) flags |= REG_NOSUB;

  if(regcomp(&re, sRegEx.c_str(), flags) != 0)
  {
   return false;
  }

  if(vCaptureGroups)
  {
   int mlen = re.re_nsub + 1;
   regmatch_t *rawMatches = new regmatch_t[mlen];

   status = regexec(&re, sSubject.c_str(), mlen, rawMatches, 0);

   vCaptureGroups->clear();
   vCaptureGroups->reserve(mlen);

   if(status == 0)
   {
    for(size_t i = 0; i < mlen; i++)
    {
     vCaptureGroups->push_back(sSubject.substr(rawMatches[i].rm_so, rawMatches[i].rm_eo - rawMatches[i].rm_so - 1));
    }
   }

   delete[] rawMatches;
  }
  else
  {
   status = regexec(&re, sSubject.c_str(), 0, NULL, 0);
  }

  regfree(&re);

  return (status == 0);
 }
0 голосов
/ 15 ноября 2017

Это работает для меня:

'\#include\s*(<([^"<>|\b]+)>|"([^"<>|\b]+)")'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...