我有一个CSV,方式如下。"India,Inc"是一个公司名称,它是单个值,其中包含 ,其中
如何在 LINQ 中获取值
12321,32432,423423,凯文·奥布莱恩,"印度公司",234235,23523452,235235
假设您将始终拥有指定的列,并且唯一的变量是公司名称可以包含逗号,则此UGLY代码可以帮助您实现目标。
var file = File.ReadLines("test.csv");
var value = from p in file
select new string[]
{ p.Split(',')[0],
p.Split(',')[1],
p.Split(',')[2],
p.Split(',')[3],
p.Split(',').Count() == 7 ? p.Split(',')[4] :
(p.Split(',').Count() > 7 ? String.Join(",",p.Split(',').Skip(4).Take(p.Split(',').Count() - 7).ToArray() ) : ""),
p.Split(',')[p.Split(',').Count() - 3],
p.Split(',')[p.Split(',').Count() - 2],
p.Split(',')[p.Split(',').Count() - 1]
};
正则表达式可以工作,由于递归性质,有点讨厌,但它确实实现了您的目标。
List<string> matches = new List<string>();
string subjectString = "12321,32432,423423,Kevin O'Brien,"India,Inc",234235,23523452,235235";
Regex regexObj = new Regex(@"(?<="")b[123456789a-z,']+b(?="")|[123456789a-z']+", RegexOptions.IgnoreCase);
Match matchResults = regexObj.Match(subjectString);
while (matchResults.Success)
{
matches.Add(matchResults.Value);
// matched text: matchResults.Value
// match start: matchResults.Index
// match length: matchResults.Length
matchResults = matchResults.NextMatch();
}
在大多数情况下,这应该就足够了。 它处理带引号的字符串、其中带有双引号的字符串以及嵌入的逗号。
var subjectString = "12321,32432,423423,Kevin O'Brien,"India,Inc",234235,"Test End""","""Test Start","Test""Middle",23523452,235235";
var result=Regex.Split(subjectString,@",(?=(?:[^""]*""[^""]*"")*[^""]*$)")
.Select(x=>x.StartsWith(""") && x.EndsWith(""")?x.Substring(1,x.Length-2):x)
.Select(x=>x.Replace("""","""));
但是,如果您有一个包含单双引号的字段,并且字符串本身没有用双引号括起来,那么它确实会中断 - 这在CSV文件的大多数定义中是无效的,其中任何包含CR,LF,逗号或双引号的字段都必须括在双引号中。
对于小型 CSV 文件,您应该能够重复使用相同的正则表达式来换行。 较大的你会想要一个更好的实现。 将双引号替换为 LF,并删除匹配的引号(不带引号的 LF)。 然后再次使用正则表达式将引号替换为 CR,并在匹配时拆分。
另一种选择是使用CSVHelper而不是托盘来重新发明轮子
var csv = new CsvHelper.CsvReader(new StreamReader("test.csv"));
while (csv.Read())
{
Console.WriteLine(csv.GetField<int>(0));
Console.WriteLine(csv.GetField<string>(1));
Console.WriteLine(csv.GetField<string>(2));
Console.WriteLine(csv.GetField<string>(3));
Console.WriteLine(csv.GetField<string>(4));
}
指导
我推荐 LINQ 到 CSV,因为它足够强大,可以处理特殊字符,包括逗号、引号和小数。他们真的为你解决了很多这些问题。
只需几分钟即可完成设置,而且非常值得花时间,因为您不会像使用自定义代码那样遇到这些类型的问题。以下是基本步骤,但一定要按照上面链接中的说明进行操作。
- 安装 Nuget 包
- 创建一个类来表示行项目(以字段在 csv 中的命名方式命名字段)
- 使用 CsvContext.Read() 读取 IEnumerable,您可以使用 LINQ 轻松操作
- 使用 CsvContext.Write() 将列表或 IEnumerable 写入 CSV
这非常容易设置,代码很少,并且比自己动手更具可扩展性。
因为您只读取逗号分隔的值,所以如果您只是将它们视为任何其他字符,则空格应该不会引起问题。
var values = File.ReadLines(path)
SelectMany(line => line.Split(','));