Text::CSVでエクセルが吐き出すふざけたCSVを処理するメモ

エクセルはいい子ちゃんなので、とっても素敵なCSVを作ってくれます。

例えばこんなの

"7","sample","あいうえお?","か","きくけこ
<a href="foo.html">さしすせそ</a>
<a href="bar.html">たちつてと</a>なにぬねの","はひふへほ"

"〜"の中の「"」をエスケープしてくれないという素晴らしい仕様。 と思ったら、「""」でエスケープしてくれるようになったので、混乱中。

きっとオリジナルのデータが上のようなものだと、「イレギュラーなCSVだ」とエクセルが判断し、可能な限りオリジナルのまま留めようとする、エクセルの親心のようなものが発生しているのではないかと思う。

これをperlのText::CSVを使って処理をするというメモ。 というわけで、これは上記のようなイレギュラーなCSVを強引に処理するというメモ。

#!/usr/bin/perl

use strict;
use warnings;

use IO::File;
use Text::CSV;
use Data::Dumper;

my $fh = IO::File->new or die $!;
$fh->fdopen(fileno(STDIN),"r");

my $csv = new Text::CSV(
    {
        binary              => 1,
        allow_loose_escapes => 1, 
        allow_loose_quotes  => 1,
        # escape_charとquote_charが同じだとだめ(とpodに書いてある)
        # escape_char => '\\'だと文字化ける(SJISの場合)
        escape_char         => undef,
    }
);

my @lines;
until ($fh->eof) {
    my $array = $csv->getline($fh);
    push @lines, $array;
}

$fh->close;

print Dumper(\@lines);
binary              => 1,
allow_loose_escapes => 1, 
allow_loose_quotes  => 1,
escape_char         => undef,

がミソ。エクセルがエスケープしてくれないので、escape_charはundefとしているが、最近のエクセルだとまた違うのかもしれない。 なんか知らんがエスケープしてくれたので、

binary              => 1,

だけでオッケーになった。むかつく。