嵌入双引号的CSV解析

时间:2010-12-18 20:22:33

标签: c++ algorithm parsing csv

我写了一个简单的CSV文件解析器。但在查看wiki page on CSV formats之后,我注意到了基本格式的一些“扩展”。通过双引号特别嵌入逗号。我设法解析了那些,但是还有第二个问题:嵌入双引号。

示例:

12345,“ABC”,“IJK”“XYZ” - > [1234]和[ABC,“IJK”XYZ]

我似乎无法找到区分封闭双引号和无引号的正确方法。所以我的问题是解析CVS格式的正确方法/算法是什么?如上所述?

5 个答案:

答案 0 :(得分:4)

我通常想到的方法基本上是将引用的值看作单个,不带引号的值一系列双引号值,这些值构成一个由引号连接的值。也就是说,

  • 解析行中的下一个原子:
    • 读取第一个非空格字符
    • 如果当前字符不是引用:
      • 标记当前地点
      • 阅读下一个逗号或换行符
      • 在逗号之前返回标记和字符之间的文本(如果适用,删除空格)
    • 如果当前字符是引用:
      • 创建一个空字符串缓冲区
      • 而当前字符引用
        • 标记当前位置+1(跳过引号字符)
        • 阅读下一篇文章
        • 如果缓冲区不为空,请附加报价
        • 在缓冲区附加标记与当前位置前的字符之间的文本(以删除两个引号)
        • 推进一个字符(超过刚读过的引用)
      • 阅读下一个逗号或换行符
      • 返回缓冲区

基本上,拆分引用字符串的每个双引号段,然后用引号将它们连在一起。因此:"ABC, ""IJK"" XYZ"变为ABC, IJK XYZ,而后者变为ABC, "IJK" XYZ

答案 1 :(得分:2)

我会使用单个字符预测来执行此操作,因此如果您正在扫描字符串并找到双引号,请查看 next 字符以查看它是否也是双引号。如果是,则该对表示输出中的单个双引号字符。如果它是任何其他字符,你正在查看引用字符串的结尾(希望下一个字符是逗号!)。在查看下一个字符时,请务必考虑行尾情况。

答案 2 :(得分:1)

双引号("")是文字双引号,而单引号(")用于封闭文本(包括逗号)。

这是csv字段的正则表达式,如果这样可以简化:

([^",\n][^,\n]*)|"((?:[^"]|"")+)"

如果字段不在引号中,则组1将包含该字段;如果字段在引号中,则组2将包含该字段,减去周围的引号。在这种情况下,只需将""的所有实例替换为"

答案 3 :(得分:1)

如果你找到双引号,那么你应该在单词/字符串的末尾寻找双引号。如果找不到,那就有错误。引用相同。

我建议您尝试使用Flex / Bison来为CSV文件编写解析器。这两个工具都可以帮助您生成解析器,然后您可以将C文件与解析器一起使用,并从C ++程序中调用它。 在Flex上,您可以创建一个可以找到令牌的扫描仪,例如“word”或“”word“”。在Bison上,您可以定义语法。

答案 4 :(得分:1)

我建议您阅读:Stop Rolling Your Own CSV ParserCSV RFC。第一个实际上只是想要你使用他们的C#CSV解析器的人,但仍然解释了许多问题。

您的解析器应该一次检查一个角色。我为parser in D使用了双重布尔策略。每个引号切换天气是否引用字符串。在引用的单元格中,当您点击引号时标记,并关闭引用。如果下一个字符是引号,则启用引号,将结果添加引号并关闭该标志。如果下一个字符不是引号,那么该标志将被关闭,因此引用。