C regex comment faire correspondre une chaîne se terminant par “ou une chaîne vide?”

J’essaie de produire du code pour lire les entrées d’un fichier texte séparé par des virgules, ligne par ligne. Je ne suis intéressé que par 3 des champs, alors je saute le rest. Le problème est que 2 des champs sont des chaînes entre guillemets et que l’un d’eux est facultatif.

Par exemple, deux lignes successives peuvent ressembler à:

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 

Étant donné que les chaînes ne m’intéressent pas (seulement quelques chiffres), je les saute à l’aide de l’opérateur * de scanf. Pour la première chaîne, c’est facile, puisqu’il s’agit d’un champ obligatoire. Je peux donc ignorer la première correspondance entre guillemets doubles dans une regex de tout jusqu’à la deuxième guillemet double, comme ceci:

 \"%*[^\"] 

Ce qui me pose problème, c’est le deuxième champ, juste après le premier. Le problème est que ce champ est facultatif. ainsi il peut avoir du texte, il ne peut pas. À chaque fois que cela ne fonctionne pas, l’expression régulière que j’ai énumérée ci-dessus ne fonctionne pas correctement et l’opération de scanf échoue pour cette ligne. En dépit de tous mes efforts, je ne peux pas produire une expression régulière qui mette tout en correspondance jusqu’au deuxième guillemet double, ainsi que des chaînes vides correspondantes. Est-ce que quelqu’un sait comment je pourrais modifier mon regex pour remplir une telle fonction?

ps voici un exemple de mon opération scanf:

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

Ce qui suit est un parsingur de base CSV:

 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 ssortingng 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); } 

Remarque: traitement des sauts de ligne dans une chaîne entre guillemets

Souvent, l’parsingur est appelé avec une ligne que l’appelant a lue. Pour pouvoir traiter les retours à la ligne / sauts de ligne qui se trouvent dans une chaîne entre guillemets, l’parsingur doit traiter l’affichage de \n en obtenant la ligne suivante. La signature de readCSVfield doit alors inclure le tampon de ligne et sa taille.