C expresión regular ¿cómo hacer coincidir cualquier cadena que termine con “o cualquier cadena vacía?

4 minutos de lectura

C expresion regular ¿como hacer coincidir cualquier cadena que termine
Ammar

Estoy tratando de producir un código para leer la entrada de un archivo de texto separado por comas línea por línea. Solo estoy interesado en 3 de los campos, así que me saltearé el resto. El problema es que 2 de los campos son cadenas entre comillas, y uno de ellos es opcional.

Por ejemplo, dos líneas sucesivas podrían verse así:

0,,10004,10004,"Albany Hwy After Galliers Av","",-32.13649428,116.0176090070,3
0,,10005,10005,"Albany Hwy Armadale Kelmscott Hospital","Armadale Kelmscott Hospital",-32.13481555555560,116.017707222222,3

Como no estoy interesado en las cadenas (solo estoy interesado en algunos de los números), solo los estoy saltando usando el operador * en scanf. Para la primera cadena, es fácil, ya que es un campo obligatorio, así que puedo omitir la primera coincidencia de comillas dobles a una expresión regular de todo hasta la segunda comilla doble, así:

\"%*[^\"]

Con lo que tengo problemas es con el segundo campo, justo después del primero. El problema es que este campo es opcional; por lo tanto, puede tener texto, puede que no. Cuando no es así, la expresión regular que mencioné anteriormente no funciona correctamente y toda la operación scanf falla para esa línea. A pesar de mis mejores esfuerzos, no puedo producir una expresión regular que coincida exitosamente con todo hasta la segunda comilla doble, así como también con cadenas vacías. ¿Alguien sabe cómo podría modificar mi expresión regular para realizar tal función?

ps aquí hay un ejemplo de cómo se ve mi operación scanf:

    res = sscanf(buf, "%*d,,%ld,%*ld,\"%*[^\"]\",\"%*[]\",%lf,%lf,%*d", &cursid, &curslat, &curslong);

  • los scanf familia de funciones lo hace no utilizar expresiones regulares.

    – Un tipo programador

    2 de septiembre de 2015 a las 9:22

  • Lo siento, mi error, esto no es expresión regular. Solo está utilizando el %[chars] función de scanf, donde todo coincide [chars] es leído. La pregunta sigue en pie sobre cómo puedo lograr lo que estoy tratando de hacer.

    – Ammar

    2 de septiembre de 2015 a las 9:25


  • En cuanto a cómo leer su archivo CSV, no es tan simple como uno pensaría porque los formatos de archivo CSV generalmente contienen muchas esquinas que los hacen más difíciles de analizar de lo que uno pensaría. Intente encontrar una biblioteca existente para leer y analizar su archivo.

    – Un tipo programador

    2 de septiembre de 2015 a las 9:26

  • fscanf es totalmente inadecuado para leer CSV. Debes leer línea por línea usando fgets y luego analice la cadena usted mismo. Pero como se señaló en otro comentario, intente encontrar algún código por ahí.

    – Jabberwocky

    2 de septiembre de 2015 a las 9:28

  • Bueno, estoy leyendo la línea usando fgets y luego analizándola usando sscanf. no estoy usando fscanf

    – Ammar

    2 de septiembre de 2015 a las 9:29

1647643214 166 C expresion regular ¿como hacer coincidir cualquier cadena que termine
Pablo Ogilvie

El siguiente es un analizador CSV básico:

void readCSVline(char *line);
char *readCSVfield(char *line, char *buf);
void readCSVdemo(void)
{
    char line[]= "0,,10004,10004,\"Albany Hwy After Galliers Av\",\"\",-32.13649428,116.0176090070,3";
    readCSVline(line);

}
/* readCSVline is where you put your "intelligence* about fields to read
 * and what to do with them
 */
void readCSVline(char *line)
{
    char field1[80], *lineptr=line;
    int nfields=0;

    while (*lineptr) {
        lineptr= readCSVfield(lineptr, field1);
        printf("%s\n", field1);
        nfields++;
    }
    printf("%d fields read.\n", nfields);
}
/* readCSVfield reads a field from a CSV line until the next comma or end-of-line.
 * It returns where the reading stopped.
 */
char *readCSVfield(char *line, char *buf)
{
    int instr= FALSE;   // track whether we are in a string
    char *cptr= line;

    while (*cptr)
    {
        if (instr) {
            if (*cptr=='"') {
                char cc= *++cptr;
                if (cc=='"')        // escaped double quote
                    *buf++ = '"';
                else {
                    *buf="\0";
                    cptr--;
                    instr= FALSE;
                }
            }
            else *buf++ = *cptr;
        }
        else switch (*cptr) {
        case '"': instr= TRUE; break;
        case ',': cptr++; *buf="\0"; return(cptr);
        case ' ': case '\t': case '\n': case '\r': break;
        default: *buf++ = *cptr;
        }
        cptr++;
    }
    *buf="\0";
    return(cptr);
}

Nota: procesamiento de saltos de línea en una cadena entre comillas

A menudo, se llama al analizador con una línea que la persona que llama ha leído. Para poder procesar retornos de carro/saltos de línea que están en una cadena entrecomillada, el analizador debe procesar ver un \n obteniendo la siguiente línea. la firma para readCSVfield luego debe incluir el búfer de línea y su tamaño.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad