2009-09-14 17 views
6

Potrzebuję pomocy próbując dopasować C to plik z pełną ścieżką tak:Wyrażenie regularne, aby dopasować C plik #include

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

Do tej pory (dostosowanym z innego wyrazu znalazłem):

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

Ale trochę utknęłam w tym punkcie - nie pasuje w drugim przypadku i nie jestem pewien, jak zwrócić wynik meczu, np. Ścieżka pliku z powrotem do regcomp ().

BTW Spojrzałem na regexplib.com, ale nie mogę znaleźć niczego odpowiedniego.

Edit: Tak, jestem w sumie regexp początkujących, używając POSIX regex z regmatch_t i przyjaciółmi ...

+0

Należy pamiętać, że nie może być spacji między „#” i „obejmować”. Zauważ też, że istnieje trzecia forma: #include MACRONAME. MACRONAME musi rozwinąć się do lub "czegoś". –

+0

Termin "środkowy" z jego złożoną klasą znaków wyklucza twoją drugą sprawę, mówiąc "to, co jest w środku, nie może zawierać /". –

Odpowiedz

5

Oto co napisał:

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

Czy pasuje?

+0

Tak, również ładnie i prosto. Prawdopodobnie poprawię ustawienia, aby być bardziej odpornym na przestrzenie. Dzięki! – Justicle

+0

Zaproponuj "(<[^>] +>)", aby lepiej zidentyfikować i podobne dla innych terminów. W przeciwnym razie '#include // a> b' pobiera złe informacje. Czy potrafisz też używać nawiasów nieprzechwytujących? To zależy od biblioteki regex. –

+0

@ Jonathan oczywiście mógłbym używać niewychodzących nawiasów ... Co to jest? btw, edytowałem regex, ty =) –

2

możesz spróbować tej regex:

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

wolę mieć regex oddzielna dla
#include <>
i
#include ""

4

dałoby to lepsze resu lts:

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

Następnie należy spojrzeć na pierwszą grupę przechwytywania, gdy pojawi się mecz.

Nie mówisz, jakiego języka używasz, czynnik, o którym wspomniałeś regcomp() prowadzi mnie do przekonania, że ​​używasz biblioteki regex POSIX w C. Jeśli to prawda, to chcesz użyć funkcji regexec i użyj parametrów nmatch i pmatch, aby uzyskać pierwszą grupę przechwytywania.

+0

Yep POSIX regex to, będę aktualizować pytanie. – Justicle

+0

Teoretycznie możesz mieć "#include " lub "#include" name> this "' - dawno temu, drugi mógł pojawić się w C dla PRIMOS. W praktyce żadne z nich nie jest prawdopodobne. –

+0

Jonathan: Tak, przyszło mi do głowy, że nie jest to ściśle oparte na standardzie, ale doszedłem do wniosku, że nazwy plików zawierające podwójne cudzysłowy lub więcej niż znaki rzadko, jeśli kiedykolwiek pojawią się w dziczy (oraz pliki źródłowe/nagłówkowe C) Wydaje się, że pasuje do "mniej dziwnego" końca widma nazw plików. –

1

Nie jest szczególnie dobrze przetestowane, ale pasuje do dwóch przypadkach:

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

Jedynym problemem jest to, że ze względu na> rzeczy <, a wynik może być w grupie przechwytywania 2 lub 3, więc zalecana sprawdź, czy 2 jest puste, a następnie użyj 3 ... Zaletą niektórych innych odpowiedzi jest to, że nie pasują do czegoś takiego: #include "bad.h> czy to: #include < złe < <h>

A oto przykład jak używać (zawija) regcomp & przyjaciele:

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

Hej! Nie pasuję do '#include 'bad.h>'! :( –

+0

a) Przepraszamy, nie widziałem twojej odpowiedzi b) Twoja osoba będzie np. Pasowała do #include c) Również moja wiadomość również zostanie dopasowana " file.h '. D'oh. Przepraszam' about that. Głupi PHP.Tak dobrym pomysłem byłoby połączenie Klemensa do ogólnego pomysłu i mojego do sprawdzania poprawności – KiNgMaR

+0

Haha dzięki Nie muszę pasować tylko zwykłe głupie zawiera. – Justicle

2

jeśli chcesz więcej precyzyjne rozwiązanie, które pozwala również komentarze przed to plik jako, na przykład,

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

jest:

^(?:\s*|\s*\/\*.*?\*\/)\s*#include\s*(?:(?:<)(?<PATH>.*?)(?:>)|(?:")(?<PATH>.*?)(?:")) 
0

Działa to dla mnie:

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