【问题标题】:C++ String splitting but escaping all delimiters in quotationsC ++字符串拆分但转义引号中的所有分隔符
【发布时间】:2017-01-19 10:34:37
【问题描述】:

使用 C++,我想拆分字符串(在这种情况下为 CSV 文件)的行,其中某些字段可能包含转义的分隔符(使用“”)并且应该被视为文字。我已经查看了已经提出的各种问题,还没有找到我的问题的直接答案。

CSV 文件数据示例:

Header1,Header2,Header3,Header4,Header5
Hello,",,,","world","!,,!,",","

拆分后所需的字符串向量:

["Hello"],[",,,"],["world"],["!,,!,"],[","]

注意:CSV 仅在数据列数等于标题列数时才有效。

更喜欢非增强/第三方解决方案。效率不是首要任务。

编辑: 下面从@ClasG 实现正则表达式的代码至少满足上述情况。我正在起草边缘测试用例,但很想听听它何时/何​​地崩溃......

std::string s = "Hello,\",,,\",\"world\",\"!,,!,\",\",\"\"";    
std::string rx_string = "(\"[^\"]*\"|[^,]*)(?:,|$)";
regex e(rx_string);
std::regex_iterator<std::string::iterator> rit ( s.begin(), s.end(), e );
std::regex_iterator<std::string::iterator> rend;

while (rit!=rend) 
{
    std::cout << rit->str() << std::endl;
    ++rit;
}    

【问题讨论】:

  • 没有标准的 csv 库。为什么您如此热衷于避免使用第三方解决方案?
  • @BoBTFish 很乐意考虑基于第三方的答案。只是说明什么是这个用例的理想选择。
  • 使用一个非常简单的状态机来解析每个字符。完毕。没有第 3 方库。
  • csv 看起来很简单,但可以包含很多极端情况。您应该首先阅读 wikipedia 对此的评论。恕我直言,您应该首先准确地指定您需要的内容(字段中的分隔符、字段中的引号字符、字段中的行尾等),构建一系列测试用例,然后实现它手动并测试您的实现。或者,选择一个 csv 库,控制其规格是否满足您的要求,对其进行测试并使用它。

标签: c++ regex csv stl


【解决方案1】:

这不是一个完整的 (c++) 解决方案,而是一个正则表达式,可能会将您推向正确的方向。

类似的正则表达式

("[^"]*"|[^,]*)(?:,|$)

将匹配各个列。 (请注意,它不处理转义引号。)

See it here at regex101.

【讨论】:

  • 嗯,我不会这样做,但是您是否在所有可能的 csv 极端情况下测试了您的正则表达式,主要是:分隔符、新行或字段中的引号字符?
  • 我不确定支持的语言的正则表达式是否与 c++ 匹配,但为酷资源链接 +1。
  • @SergeBallesta 如前所述-“不是一个完整的解决方案”。但是它确实处理了给出的示例,我认为这是可能的情况的代表。
  • 那你用的是什么风格的c++? 11、14...?
  • @ClasG VS2012 所以至少可以使用 c++11。将尝试正则表达式测试应用程序。你是说regex101的php正则表达式会直接翻译吗? (根本不是 C++ 正则表达式专家,但渴望学习)
【解决方案2】:

这不是答案,但恕我直言,作为评论太长了。

CSV 是一种看似简单但实际上非常糟糕的存储格式。

您正在寻找的机器人是 Boost.Spirit。

灵魂大师的名字(堆栈溢出)是@sehe。

在这里查看他的答案:https://stackoverflow.com/a/18366335/2015579

请相信sehe,而不是我。

【讨论】:

  • 将需要更多的专业知识来欣赏他的实施。不过谢谢。
  • @Willeman boost.sprit 为您生成解析器状态机。在您掌握窍门之前,它非常复杂。
猜你喜欢
  • 1970-01-01
  • 2017-01-05
  • 1970-01-01
  • 1970-01-01
  • 2015-03-07
  • 1970-01-01
  • 1970-01-01
  • 2013-02-17
  • 2010-12-17
相关资源
最近更新 更多