2010-04-05 23 views
19

Estoy tratando de extraer una cadena de otra utilizando expresiones regulares. estoy usando las funciones de expresiones regulares POSIX (regcomp, regexec ...), y fallar en la captura de un grupo ...¿Cómo se captura un grupo con expresiones regulares?

Por ejemplo, dejar que el patrón sea algo tan simple como "MAIL FROM:<(.*)>"
(con REG_EXTENDED cflags)

quiero capturar todo lo que entre '<' y '>'

Mi problema es que me da regmatch_t los límites de todo el patrón (MAIL FROM: < ...>) en lugar de simplemente lo que hay entre el paréntesis ...

¿Qué me estoy perdiendo?

Gracias de antemano,

de edición: un código

#define SENDER_REGEX "MAIL FROM:<(.*)>" 

int main(int ac, char **av) 
{ 
    regex_t regex; 
    int status; 
    regmatch_t pmatch[1]; 

    if (regcomp(&regex, SENDER_REGEX, REG_ICASE|REG_EXTENDED) != 0) 
    printf("regcomp error\n"); 
    status = regexec(&regex, av[1], 1, pmatch, 0); 
    regfree(&regex); 
    if (!status) 
     printf( "matched from %d (%c) to %d (%c)\n" 
      , pmatch[0].rm_so 
      , av[1][pmatch[0].rm_so] 
      , pmatch[0].rm_eo 
      , av[1][pmatch[0].rm_eo] 
      ); 

    return (0); 
} 

salidas:

$./a.out "MAIL FROM:<abcd>$" 
matched from 6 (M) to 22 ($) 

solución:

como dijo RarrRarrRarr, los índices son de hecho en pmatch[1].rm_so y pmatch[1].rm_eo
por lo tanto se convierte en regmatch_t pmatch[1];regmatch_t pmatch[2];
y regexec(&regex, av[1], 1, pmatch, 0); convierte regexec(&regex, av[1], 2, pmatch, 0);

gracias :)

Respuesta

9

El elemento 0 ª de la matriz pmatch de estructuras regmatch_t contendrá el los límites de toda la cuerda coinciden, como habrás notado. En su ejemplo, le interesa el regmatch_t en el índice 1, no en el índice 0, para obtener información sobre la cadena que coincide con la subexpresión.

Si necesita más ayuda, trate de editar la pregunta para incluir una pequeña muestra de código real para que las personas pueden detectar más fácilmente el problema.

+0

Gracias, que fue el tema :) – Sylvain

16

Aquí hay un ejemplo de código que demuestra la captura de múltiples grupos.

Puede ver que el grupo '0' es la coincidencia completa, y los grupos subsiguientes son las partes entre paréntesis.

Tenga en cuenta que esto solo capturará la primera coincidencia en la cadena fuente. Here's a version that captures multiple groups in multiple matches.

#include <stdio.h> 
#include <string.h> 
#include <regex.h> 

int main() 
{ 
    char * source = "___ abc123def ___ ghi456 ___"; 
    char * regexString = "[a-z]*([0-9]+)([a-z]*)"; 
    size_t maxGroups = 3; 

    regex_t regexCompiled; 
    regmatch_t groupArray[maxGroups]; 

    if (regcomp(&regexCompiled, regexString, REG_EXTENDED)) 
    { 
     printf("Could not compile regular expression.\n"); 
     return 1; 
    }; 

    if (regexec(&regexCompiled, source, maxGroups, groupArray, 0) == 0) 
    { 
     unsigned int g = 0; 
     for (g = 0; g < maxGroups; g++) 
     { 
      if (groupArray[g].rm_so == (size_t)-1) 
      break; // No more groups 

      char sourceCopy[strlen(source) + 1]; 
      strcpy(sourceCopy, source); 
      sourceCopy[groupArray[g].rm_eo] = 0; 
      printf("Group %u: [%2u-%2u]: %s\n", 
       g, groupArray[g].rm_so, groupArray[g].rm_eo, 
       sourceCopy + groupArray[g].rm_so); 
     } 
    } 

    regfree(&regexCompiled); 

    return 0; 
} 

Salida:

Group 0: [ 4-13]: abc123def 
Group 1: [ 7-10]: 123 
Group 2: [10-13]: def 
Cuestiones relacionadas