2009-09-14 12 views
6

Necesito ayuda tratando de coincidir con un C incluyen archivo con ruta completa de esta manera:Expresión regular para que coincida con el archivo # include C

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

Hasta ahora he (adaptado de otra expresión que encontré):

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

Pero, estoy atascado en este punto - no coincide en el segundo caso, y no estoy seguro de cómo devolver el resultado del partido, por ejemplo, la ruta de archivo a regcomp ()

BTW He visto regexplib.com, pero no encuentro nada adecuado.

Editar: Si yo soy un novato total de expresión regular, usando expresiones regulares POSIX con regmatch_t y amigos ...

+0

Tenga en cuenta que no puede haber espacios entre '#' y 'incluye'. Tenga en cuenta también que hay una tercera forma: #include MACRONAME. MACRONAME debe expandirse a o "algo". –

+0

El término 'medio' con su clase de caracteres complejos excluye su segundo caso al decir "lo que está en el medio no debe incluir /". –

Respuesta

5

Esto es lo que escribí:

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

¿Es adecuada?

+0

Sí, bueno y simple también. Probablemente retoque para ser más robusto con espacios. ¡Gracias! – Justicle

+0

Sugerir '(<[^>] +>)' para identificar mejor el y similar para el otro término. De lo contrario, '#include // a> b' obtiene la información incorrecta. ¿Puedes usar paréntesis que no capturen también? Eso depende de la biblioteca de expresiones regulares. –

+0

@Jonathan, por supuesto, podría usar paréntesis que no capturan ... ¿Qué es esto? por cierto, edité el regex, ty =) –

2

Puede probar esta expresión regular:

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

Yo prefiero tener expresión regular por separado para
#include <>
y
#include ""

4

Esto daría una mejor resu lts:

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

A continuación, quieren ver el primer grupo de captura cuando se obtiene una coincidencia.

No dice qué idioma está utilizando, el factor que menciona regcomp() me lleva a creer que está utilizando la biblioteca de expresiones retrospectivas POSIX en C. Si es así, entonces desea usar la función de expresión regular y use los parámetros nmatch y pmatch para obtener el primer grupo de captura.

+0

Yep POSIX regex es, voy a actualizar la pregunta. – Justicle

+0

En teoría, podría haber '#include ' o '#include" name> this "' - hace mucho tiempo, el segundo podría haber aparecido en C para PRIMOS. En la práctica, ninguno es probable. –

+0

Jonathan: sí, se me ocurrió que esto no se basa estrictamente en el estándar, pero pensé que los nombres de archivo que contienen comillas dobles o mayores que los signos rara vez aparecen en la naturaleza (y archivos de origen/encabezado C) parece caer en el extremo "menos extraño" del espectro de nombres de archivos). –

1

No especialmente bien probado, pero se adapte a sus dos casos:

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

El único problema es que debido a la> cosa < y, el resultado podría ser en el grupo de captura de 2 o 3, por lo que debe compruebe si 2 está vacío, luego use 3 ... La ventaja sobre algunas de las otras respuestas es que no coincidirá con algo así: #include "malo".h> O esto: #include < mal < <h>

Y aquí está un ejemplo de cómo utilizar (WRAP) regcomp & amigos:

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

¡Hola! No juego '#include" bad.h> '! :( –

+0

a) Disculpa, no vi tu respuesta. b) La tuya, por ejemplo, coincidirá con #include c) También mencioné que la mía también coincidirá" file.h '. D'oh. Perdón por eso. Estúpido PHP. Así que una buena idea sería combinar la idea general de Clement y la mía para su validación. – KiNgMaR

+0

Haha gracias, no es necesario que coincida, simplemente incluye tonto. – Justicle

2

SI desea una solución más precisa que permite también comenta antes de la incluir archivos como, por ejemplo,

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

es:

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

Esto funciona para mí:

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