拆分字符串并忽略引号内的分隔符

13
我正在使用.NET的String.Split方法将一个字符串按逗号分隔,但我想忽略用双引号括起来的字符串。我已经阅读过一篇文章,其中提到了一种

例如,下面的字符串。

Fruit,10,"Bananas, Oranges, Grapes"

我希望能够获得以下内容

Fruit
10
"Bananas, Oranges, Grapes"

目前我得到了以下输出

Fruit
10
"Bananas
 Oranges
 Grapes"
enter code here

在遵循建议和提供的答案后,这是我最终得到的一个示例。 (显然对我有效)

Imports Microsoft.VisualBasic.FileIO

Dim fileReader As New TextFieldParser(fileName)

fileReader.TextFieldType = FieldType.Delimited
fileReader.SetDelimiters(",")
fileReader.HasFieldsEnclosedInQuotes = True

While fileReader.EndOfData = False


Dim columnData() As String = fileReader.ReadFields

' Processing of field data

End While

4
请使用现有的 CSV 解析器,例如 TextFieldParser这个,它们都支持引号包含的情况。 - Tim Schmelter
FileHelpers 是一个很好的 CSV 库。 - Tim S.
可能会有帮助:https://dev59.com/WWMl5IYBdhLWcg3wwZTc - Duncan Finney
@Time Schmelter按照您的建议尝试了一下,成功了,谢谢。 - Tachi
4个回答

13

像评论中提到的那些解析器一样,使用解析器会更好。尽管如此,以下是使用正则表达式的方法:

,(?=(?:[^"]*"[^"]*")*[^"]*$)
< p > 正向先行断言 ((?= ... )) 确保在逗号分隔之前有偶数个引号(即它们要么成对出现,要么没有出现)。

[^"]* 匹配非引号字符。


1
这太慢了!在我的电脑上,读取一个300k行的CSV文件从大约2秒变成了大约111秒(并行处理从4秒变成了40秒)。我尝试了一些替代方案,并发现老派的VisualBasic TextFieldParser实际上更快(33秒,非并行),并且自动处理“引号中的逗号”问题。当然,TextFieldParser比如StreamReader要慢。如果没有第三方CSV库,似乎TextFieldParser类是处理不干净的CSV文件时性能最重要的选择。 - jspinella
@jspinella 当然,专门的解析器会更快,因为它已经针对此进行了优化。问题在于可能存在边缘情况(数据源无法控制且知道存在结构问题),这些解析器可能只会抛出错误,而人们必须采用其他手工方法才能处理数据。虽然不是理想的解决方案,但至少可以取得一些进展。 - Jerry

3
我发现以下是最简单的方法,我们可以这样做。
string fruits = "Fruit,10,"Bananas, Oranges, Grapes"";
string[] fruitsArr = Regex.Split(fruits, ",(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))");

输出:

fruitsArr[0] = "Fruit"
fruitsArr[1] = "10"
fruitsArr[2] = "\"Bananas, Oranges, Grapes\""

如果您需要纯字符串数据,可以使用以下方法进行操作: fruitsArr[2].Replace("\"", "") 该代码片段可以将第三个元素中的引号删除,并返回一个字符串。

1

一个快速的解决方法是预处理引号内的逗号,并将其替换为另一个分隔符,拆分值,然后使用该分隔符进行后处理,将其替换为原始逗号。


0

如果使用C#,可以使用

        string searchQuery = "Fruit,10,\"Bananas, Oranges, Grapes\"";
        List<string> list1 = Regex.Matches(searchQuery, @"(?<match>\w+)|\""(?<match>[\w\s,]*)""").Cast<Match>().Select(m => m.Groups["match"].Value).ToList();
        foreach(var v in list1)
        Console.WriteLine(v);

输出:

水果

10

香蕉,橙子,葡萄


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接