[JavaScript][Perl] 続・正規表現を使ったCSVパーサ

[JavaScript][Perl] 続・正規表現を使ったCSVパーサ

2008-01-29

正規表現を使ったCSVパーサの続き。

トークン化したCSVを解釈するコードをJavaScriptとPerlで書いた。二つのロジックはほぼ同じ。

それぞれ、第一引数には解釈するCSVテキストを渡し、第二引数ではfield間の区切り文字を指定する。デフォルトはコンマ(,)。戻り値は、CSVを解釈した2次元配列(Perlの場合はリファレンス)。

JavaScript

function parseCSV(text, delim) {
    if (!delim) delim = ',';
    var tokenizer = new RegExp(delim + '|\r?\n|[^' + delim + '"\r\n][^' + delim + '\r\n]*|"(?:[^"]|"")*"', 'g');

    var record = 0, field = 0, data = [['']], qq = /""/g;
    text.replace(/\r?\n$/, '').replace(tokenizer, function(token) {
        switch (token) {
            case delim: 
                data[record][++field] = '';
                break;
            case '\n': case '\r\n':
                data[++record] = [''];
                field = 0;
                break;
            default:
                data[record][field] = (token.charAt(0) != '"') ? token : token.slice(1, -1).replace(qq, '"');
        }
    });

    return data;
}

Firebugで実行した結果が↓

>>> parseCSV('aaa,"bbb"\n"c""c","d,d"\n"e\ne",,""')
[["aaa", "bbb"], ["c"c", "d,d"], ["e\ne", "", ""]]

Perl

/** parseCSV.pl */
sub parseCSV($;$) {
    my($text, $delim) = (shift, shift || ',');

    $text =~ s/\n$//;
    my($record, $field, $data) = (0, 0, [['']]);
    foreach ($text =~ /$delim|\n|[^$delim"\n][^$delim\n]*|"(?:[^"]|"")*"/g) {
        $data->[$record][++$field] = '', next if ($_ eq $delim);
        $data->[++$record] = [''], $field = 0, next if ($_ eq "\n");

        s/^"|"$//g, s/""/"/g if (/^"/);
        $data->[$record][$field] = $_;
    }

    return $data;
}

実行結果↓

>>> parseCSV qq/aaa,"bbb"\n"c""c","d,d"\n"e\ne",,""/
[["aaa", "bbb"], ["c\"c", "d,d"], ["e\ne", "", ""]]

一応は、

望み通りの動きをしてくれている様子。Excelで出力した素朴なCSVファイルを処理する分にはこの程度のスクリプトで充分そうだ。

トラックバックURL

http://liosk.blog103.fc2.com/tb.php/75-1c77255c

0件のトラックバック

0件のコメント

コメントの投稿

Subject
Name
Mail
URL
Comment

Password

Menu

プロフィール

LiosK 

Author: LiosK [発音]

ITにちょっと強い文系大学生

検索

ブログ内の記事を検索します。

タグリスト