0

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

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

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

应该给出以下结果(不带引号):

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

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

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

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

那么,有什么建议吗?

4

4 回答 4

5

我不会尝试编写我自己的 csv 解析器,那里有很多可以为您完成这项工作。

于 2012-06-29T12:53:56.950 回答
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

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

请在此处查看相同的实现,,,

于 2012-06-29T12:56:13.707 回答
1

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

下面的模式是我的标准 CSV 解析正则表达式的修改版本,它删除了空格并假设 CSV 按照您的要求是完美的。您的问题中唯一没有解决的部分是它不会删除转义/双引号。模式后给出了取消转义引号的示例。


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


这是注释模式(在 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|$)";


关于如何使用正则表达式模式的示例(嗯,可以用这种模式替换的原始模式)可以在我对类似问题的回答中找到,或者在C# pad上,或者在这里

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

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("\"\"", "\""));
}
于 2016-10-09T17:17:53.990 回答
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
于 2012-06-29T14:09:12.517 回答