16

政府の情報源 (FEC、州の有権者データベースなど) からのデータを処理しています。一貫性のない不正な形式であり、あらゆる種類の楽しい方法で CSV パーサーを壊します。

それは外部から供給され、権威があります。私はそれを解析しなければならず、再入力したり、入力時に検証したりすることはできません。それが現実さ; 私は入力を制御しません。

プロパティ:

  1. フィールドに不正な形式の UTF-8 が含まれている (例: Foo \xAB bar)
  2. 行の最初のフィールドは、既知のセットからレコード タイプを指定します。レコードの種類がわかれば、フィールドの数とそれぞれのデータの種類がわかりますが、実際に確認するまでわかりません。
  3. ファイル内の任意の行で、引用符付き文字列 ( "foo",123,"bar") または引用符なし ( foo,123,bar) を使用できます。特定の行(つまり)内で混合されている場所にはまだ遭遇していませんが、"foo",123,barおそらくそこにあります。
  4. 文字列には、内部改行、引用符、および/またはコンマ文字が含まれる場合があります。
  5. 文字列には、コンマ区切りの数字を含めることができます。
  6. データ ファイルは非常に大きくなる可能性があるため (数百万行)、これは依然としてかなり高速である必要があります。

私は Ruby FasterCSV (1.9 では単に CSV として知られています) を使用していますが、質問は言語に依存しない必要があります。

私の推測では、ソリューションには、明確なレコード区切り文字/引用文字 (ASCII RS、STX など) による前処理置換が必要になると思います。私はここで少し始めましたが、私が得るすべてのものでうまくいくわけではありません.

この種のダーティ データを確実に処理するにはどうすればよいでしょうか。

ETA: 以下は、1 つのファイルに含まれる内容の簡単な例です。

"this","is",123,"a","normal","line"
「行」、「内部」、「引用」
「短い線」、「と
を
「内部引用符」、1 つのコンマおよび
改行"
un "quot" ed,text,with,1,2,3,numbers
「引用」、「番号」、「シリーズ」、「1,2,3」
「無効な \xAB utf-8」
4

3 に答える 3

8

Ruby の CSV パーサーに渡される前に、Ruby の File をサブクラス化して、CSV ファイルの各行を処理することができます。たとえば、このトリックを使用して、非標準のバックスラッシュでエスケープされた引用符 \" を標準の二重引用符 "" に置き換える方法を次に示します。

class MyFile < File
  def gets(*args)
    line = super
    if line != nil
      line.gsub!('\\"','""')  # fix the \" that would otherwise cause a parse error
    end
    line
  end
end

infile = MyFile.open(filename)
incsv = CSV.new(infile)

while row = incsv.shift
  # process each row here
end

原則として、UTF-8 クリーンアップなど、あらゆる種類の追加処理を行うことができます。このアプローチの良い点は、ファイルを行単位で処理するため、すべてをメモリにロードしたり、中間ファイルを作成したりする必要がないことです。

于 2012-10-07T19:50:20.803 に答える
2

まず、これはかなり素朴な試みです:http: //rubular.com/r/gvh3BJaNTc

/"(.*?)"(?=[\r\n,]|$)|([^,"\s].*?)(?=[\r\n,]|$)/m

ここでの前提条件は次のとおりです。

  • フィールドは引用符で始まる場合があります。その場合、次のいずれかの引用符で終了する必要があります。
    • カンマの前
    • 新しい行の前(行の最後のフィールドの場合)
    • ファイルの終わりの前(最後の行の最後のフィールドの場合)
  • または、最初の文字が引用符ではないため、前と同じ条件が満たされるまで文字が含まれます。

これはほとんどあなたが望むことをしますが、これらのフィールドでは失敗します:

1つのコンマと
改行」

TCがコメントで指摘したように、あなたのテキストはあいまいです。あなたはすでにそれを知っていると確信していますが、完全を期すために:

  • "a"-aそれですか"a"引用符で囲みたい値をどのように表現しますか?
  • "1","2"1-- 、、、2またはとして解析される可能性があります1","2-両方とも合法です。
  • ,1 \n 2,-行の終わり、または値の改行?特に、これがその行の最後の値であると想定されているかどうかはわかりません。
  • 1 \n 2 \n 3-改行を含む1つの値?2つの値(1\n23または12\n3)?3つの値?

各行の最初の値を調べると、いくつかの手がかりが得られる可能性があります。これにより、列の数とそのタイプがわかります。これにより、ファイルを解析するために不足している追加情報が得られる可能性があります(たとえば、この行に別のフィールドがあるはずだとわかっている場合、すべての改行は現在の値に属します)。それでも、ここには深刻な問題があるようです...

于 2012-08-01T06:13:51.183 に答える