C正则表达式如何匹配以“或任何空字符串结尾的任何字符串?

我正在尝试生成代码以逐行读取逗号分隔文本文件中的输入。 我只对3个领域感兴趣,所以我正在跳过剩下的。 问题是2个字段是包含在引号中的字符串,其中一个实际上是可选的。

例如,两个连续的行可能如下所示:

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 

由于我对字符串不感兴趣(我只对一些数字感兴趣),我只是在scanf中使用*运算符跳过它们。 对于第一个字符串,它很容易,因为这是一个必填字段,所以我可以跳过第一个双引号匹配到一切的正则表达式,直到第二个双引号,如下所示:

 \"%*[^\"] 

我遇到麻烦的是第二个领域,就在第一个领域之后。 问题是这个字段是可选的; 因此它可能有文本,也可能没有。 只要不是这样,上面列出的正则表达式就无法正常工作,整个scanf操作都会失败。 尽管我付出了最大的努力,但我无法生成一个正则表达式,它可以成功匹配第二个双引号之外的所有内容,以及匹配空字符串。 有谁知道如何修改我的正则表达式来执行这样的function?

ps这里是我的scanf操作的示例:

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

以下是基本的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 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); } 

注意:处理带引号的字符串中的换行符

通常使用调用者已读取的行调用解析器。 为了能够处理带引号的字符串中的回车符/换行符,解析器必须通过获取下一行来处理看到\n 。 然后, readCSVfield的签名应包括行缓冲区及其大小。