用于解析CSV的正则表达式

时间:2012-06-29 12:49:05

标签: c# regex csv

我正在尝试编写一个可以从CSV文件中提取单个字段的正则表达式。

例如,如果在CSV文件中给出以下行:

123,    Bob    ,Bob, " Foo Bar ", "a, ""b"", c"

应该给出以下结果(没有 引号):

'123'
'Bob'
'Bob'
' Foo Bar '
'a, "b", c'

请注意,除非它们在引号内,否则应修剪前导和尾随空格。

我并不担心无效的CSV行,例如没有匹配收尾报价的开放报价。根据上述规则,您可以放心地假设CSV文件完全有效。

如果单个Regex有困难,我也可以使用多个正则表达式。但我喜欢避免使用标准的C#操作,除非它们简单而简短。 (我不想最终编写大量代码。)

那么,有什么建议吗?

4 个答案:

答案 0 :(得分:5)

我不会尝试编写我自己的csv解析器,那里有许多为你完成工作。

答案 1 :(得分:1)

有很多陷阱和错误可以使用正则表达式...尝试下面的代码它确实对我来说它很简单......

Using Reader As New Microsoft.VisualBasic.FileIO.TextFieldParser("C:\MyFile.csv")

Reader.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited

Dim MyDelimeters(0 To 0) As String
Reader.HasFieldsEnclosedInQuotes = False
Reader.SetDelimiters(","c)

Dim currentRow As String()
While Not Reader.EndOfData
    Try
        currentRow = Reader.ReadFields()
        Dim currentField As String
        For Each currentField In currentRow
            MsgBox(currentField)
        Next
    Catch ex As Microsoft.VisualBasic.FileIO.MalformedLineException
        MsgBox("Line " & ex.Message &
        "is not valid and will be skipped.")
    End Try
End While
End Using

如果发现方便,请标记为答案......;)

请在此处查看implementation ,,,

答案 2 :(得分:1)

我同意正则表达式不是“正确”的答案,但这是问题所要求的,我喜欢正确的正则表达式挑战。

下面的模式是我的standard CSV parsing regex的修改版本,它会移除空格并假设CSV完全符合您的要求。您未解决的问题的唯一部分是它不会删除转义/加倍引号。在模式之后给出了取消引号的示例。

当CSV文件/流的一行或多行/记录传递到下面的正则表达式时,它将返回每个非空行/记录的匹配项。每个匹配都将包含一个名为Value的捕获组,其中包含该行/记录中捕获的值。


这是注释模式(测试它on Regexstorm.net):

(?<=\r|\n|^)(?!\r|\n|$)                       // Records start at the beginning of line (line must not be empty)
(?:                                           // Group for each value and a following comma or end of line (EOL) - required for quantifier (+?)
  [^\S\r\n]*                                  // Removes leading spaces
  (?:                                         // Group for matching one of the value formats before a comma or EOL
    "(?<Value>(?:[^"]|"")*)"|                 // Quoted value -or-
    (?<Value>[^,\r\n]+)|                      // Unquoted/open ended quoted value -or-
    (?<Value>)                                // Empty value before comma (before EOL is excluded by "+?" quantifier later)
  )
  [^\S\r\n]*                                  // Removes trailing spaces
  (?:,|(?=\r|\n|$))                           // The value format matched must be followed by a comma or EOL
)+?                                           // Quantifier to match one or more values (non-greedy/as few as possible to prevent infinite empty values)
(?:(?<=,)(?<Value>))?                         // If the group of values above ended in a comma then add an empty value to the group of matched values
(?:\r\n|\r|\n|$)                              // Records end at EOL


这是没有所有注释或空格的原始模式。

(?<=\r|\n|^)(?!\r|\n|$)(?:[^\S\r\n]*(?:"(?<Value>(?:[^"]|"")*)"|(?<Value>[^,\r\n]+)|(?<Value>))[^\S\r\n]*(?:,|(?=\r|\n|$)))+?(?:(?<=,)(?<Value>))?(?:\r\n|\r|\n|$)


而且,这是C#转义版本。

String CSVPattern=
    @"(?<=\r|\n|^)(?!\r|\n|$)" +
    @"(?:" +
        @"[^\S\r\n]*" +
        @"(?:" +
            @"""(?<Value>(?:[^""]|"""")*)""|" +
            @"(?<Value>[^,\r\n]+)|" +
            @"(?<Value>)" +
        @")" +
        @"[^\S\r\n]*" +
        @"(?:,|(?=\r|\n|$))" +
    @")+?" +
    @"(?:(?<=,)(?<Value>))?" +
    @"(?:\r\n|\r|\n|$)";


  关于如何使用正则表达式模式的示例(以及可以用此模式替换的原始模式)可以在我对类似问题hereC# pad here或{{3}的答案中找到。 }}

注意:以上示例包含取消/取消引号的逻辑,如下所示:

if (Capture.Length == 0 || Capture.Index == Record.Index || Record.Value[Capture.Index - Record.Index - 1] != '\"')
{
    // No need to unescape/undouble quotes if the value is empty, the value starts
    // at the beginning of the record, or the character before the value is not a
    // quote (not a quoted value)
    Console.WriteLine(Capture.Value);
}
else
{
    // The character preceding this value is a quote
    // so we need to unescape/undouble any embedded quotes
    Console.WriteLine(Capture.Value.Replace("\"\"", "\""));
}

答案 3 :(得分:0)

您可以使用.NET框架中内置的TextFieldParser类。

要在C#应用程序中使用该类,您需要在以下位置添加Microsoft.VisualBasic.dll的引用(假设您安装了默认设置)

C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Microsoft.VisualBasic.dll

现在在你的C#类中有以下using语句:

using Microsoft.VisualBasic.FileIO