我写了一个简单的CSV文件解析器。但在查看wiki page on CSV formats之后,我注意到了基本格式的一些“扩展”。通过双引号特别嵌入逗号。我设法解析了那些,但是还有第二个问题:嵌入双引号。
示例:
12345,“ABC”,“IJK”“XYZ” - > [1234]和[ABC,“IJK”XYZ]
我似乎无法找到区分封闭双引号和无引号的正确方法。所以我的问题是解析CVS格式的正确方法/算法是什么?如上所述?
答案 0 :(得分:4)
我通常想到的方法基本上是将引用的值看作单个,不带引号的值或一系列双引号值,这些值构成一个由引号连接的值。也就是说,
基本上,拆分引用字符串的每个双引号段,然后用引号将它们连在一起。因此:"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 Parser和CSV RFC。第一个实际上只是想要你使用他们的C#CSV解析器的人,但仍然解释了许多问题。
您的解析器应该一次检查一个角色。我为parser in D使用了双重布尔策略。每个引号切换天气是否引用字符串。在引用的单元格中,当您点击引号时标记,并关闭引用。如果下一个字符是引号,则启用引号,将结果添加引号并关闭该标志。如果下一个字符不是引号,那么该标志将被关闭,因此引用。