使用正则表达式将csv拆分为字符串

时间:2012-12-10 07:19:32

标签: c# regex parsing csv split

我有一个正则表达式模式定义为

var pattern = ",(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))";

我正在尝试拆分一些像字符串一样的CSV来获取字段

使用此正则表达式的一些示例字符串是

_input[0] = ""; // expected single blank field
_input[1] = "A,B,C"; // expected three individual fields
_input[2] = "\"A,B\",C"; // expected two fields 'A,B' and C
_input[3] = "\"ABC\"\",\"Text with,\""; // expected two fields, 'ABC"', 'Text with,'
_input[4] = "\"\",ABC\",\"next_field\""; // expected two fields, '",ABC', 'next_field'

然而,这不起作用

_input[5] = "\"\"\",ABC\",\"next_field\"";

我期待三个字段

'"', 'ABC"', 'next_field'

但我得到两个字段

'"",ABC', 'next_field'

任何人都可以帮助这个正则表达式吗?

我认为奇怪的是第二列在值的开头和结尾没有引号,只是在结尾处。所以第一列的值为空,第二列为ABC“

谢谢, 罗布

1 个答案:

答案 0 :(得分:3)

我认为你需要更加具体地说明你的逻辑是如何处理双引号的,因为你的要求似乎相互冲突。

我认为我的快速版本与您要实现的最接近的是(请注意1)双引号丢失,因为我使用外部工具来验证正则表达式,以及2)我已更改如何检索匹配的值,请参见底部的示例):

(?<Match>(?:"[^"]*"+|[^,])*)(?:,(?<Match>(?:"[^"]*"+|[^,])*))*

它有以下逻辑:

  • 如果有双引号,则在其中包含所有内容,直到结束双引号。
  • 当达到结尾双引号时,也会包含紧随其后的双引号。
  • 如果下一个字符不是逗号,则包括它,并再次测试上述字符。
  • 如果是逗号,则结束当前匹配,并在逗号后开始新匹配。

上述逻辑与您对索引4和5的期望相冲突,但是因为我得到了:

[4] = '""' and 'ABC","next_field"'
[5] = '"""' and 'ABC","next_field"'

如果你能指出为什么上述逻辑对你的需求/期望是错误的,我会用完全正常的正则表达式编辑我的答案。

要检索您的值,您可以这样做:

string pattern = @"(?<Match>(?:""[^""]*""+|[^,])*)(?:,(?<Match>(?:""[^""]*""+|[^,])*))*";

string[] testCases = new[]{
  @"",
  @"A,B,C",
  @"A,B"",C",
  @"ABC"",""Text with,",
  @""",ABC"",""next_field""",
  @""""",ABC"",""next_field"""
};

foreach(string testCase in testCases){
  var match = System.Text.RegularExpressions.Regex.Match(testCase, pattern);
  string[] matchedValues = match.Groups["Match"].Captures
    .Cast<System.Text.RegularExpressions.Capture>()
    .Select(c => c.Value)
    .ToArray();
}