Compilación / coincidencia de expresiones regulares POSIX en C
Pregunta
Estoy tratando de hacer coincidir los siguientes elementos en la cadena pcode
:
-
u
seguido de un número de 1 o 2 dígitos phaseu
phasep
-
x
(rodeado de caracteres que no son palabras) -
y
(rodeado de caracteres que no son palabras) -
z
(rodeado de caracteres que no son palabras)
He intentado implementar una coincidencia de expresiones regulares utilizando las funciones de expresiones regulares POSIX (que se muestran a continuación), pero tengo dos problemas:
- El patrón compilado parece no tener subpatrones (es decir, compiled.n_sub == 0).
- El patrón no encuentra coincidencias en la cadena " u0 " ;, que realmente debería!
Estoy seguro de que la cadena de expresiones regulares en sí está funcionando, ya que funciona en python y TextMate, mi problema radica en la compilación, etc. en C. Cualquier ayuda para que funcione sería muy apreciada.
Gracias de antemano por sus respuestas.
if(idata=tb_find(deftb,pdata)){
MESSAGE("Global variable!\n");
char pattern[80] = "((u[0-9]{1,2})|(phaseu)|(phasep)|[\\W]+([xyz])[\\W]+)";
MESSAGE("Pattern = \"%s\"\n",pattern);
regex_t compiled;
if(regcomp(&compiled, pattern, 0) == 0){
MESSAGE("Compiled regular expression \"%s\".\n", pattern);
}
int nsub = compiled.re_nsub;
MESSAGE("nsub = %d.\n",nsub);
regmatch_t matchptr[nsub];
int err;
if(err = regexec (&compiled, pcode, nsub, matchptr, 0)){
if(err == REG_NOMATCH){
MESSAGE("Regular expression did not match.\n");
}else if(err == REG_ESPACE){
MESSAGE("Ran out of memory.\n");
}
}
regfree(&compiled);
}
Solución
Parece que tiene la intención de usar algo parecido al " extendido " POSIX sintaxis de expresiones regulares. POSIX define dos sintaxis de expresiones regulares diferentes, una '' básica '' (leer " obsoleto ") sintaxis y " extendido " sintaxis. Para usar la sintaxis extendida, debe agregar el indicador REG_EXTENDED
para regcomp
:
...
if(regcomp(&compiled, pattern, REG_EXTENDED) == 0){
...
Sin este indicador, regcomp usará el " básico " sintaxis de expresiones regulares. Hay algunas diferencias importantes, como:
- No hay soporte para el operador
|
- Los corchetes para las subcoincidencias deben escaparse,
\ (
y\)
También se debe tener en cuenta que la sintaxis de expresión regular extendida POSIX no es 1: 1 compatible con la expresión regular de Python (no sé acerca de TextMate). En particular, me temo que esta parte de su expresión regular no funciona en POSIX, o al menos no es portátil:
[\\W]
La forma POSIX de especificar caracteres que no son espacios es:
[^[:space:]]
Toda su expresión regular para POSIX debería verse así en C:
char *pattern = "((u[0-9]{1,2})|(phaseu)|(phasep)|[^[:space:]]+([xyz])[^[:space:]]+)";