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ファイル/ストリームの1つ以上の行/レコードが以下の正規表現に渡されると、空でない各行/レコードの一致が返されます。各一致には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#パッド、またはここにあります。

注:上記の例には、以下に示すように、引用符をエスケープ解除/アンダブルするためのロジックが含まれています。

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

.NETFrameworkに組み込まれている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 に答える