« perl でリンクを抽出する | メイン | 二重起動の防止 »

2004年08月03日

CSV の行を分解

CSVをコンマで分けるのは一見簡単そうであるが、実は奥が深い。Perl では Text::CSV_XS モジュールを使うのが便利だ。

たとえば、split 関数を使って「,」で分ければ、次のような単純な例はうまくいく。
$line='A,BB,CCC,,D';
@values=split(/,/,$line);
しかし、これでは「,」や「"」を含む値を適切に扱うことはできない。値の中に「,」や「"」を含むときは値を「"」で囲み、含まれる「"」は「""」と記述するのだが、単純に「,」で切っては当然うまくいかない。

Perlメモ(http://www.din.or.jp/~ohzaki/perl.htm#CSV2Values)に詳しくやり方が書いてあった。難しくて解読困難だ。(^^;
$tmp=$line='"""北海道,札幌市""",ABC,"XX,XX","abc"';
$tmp=~s/(?:\x0D\x0A|[\x0D\x0A])?$/,/;
@values=map {/^"(.*)"$/?scalar($_=$1,s/""/"/g,$_):$_}
        ($tmp =~ /("[^"]*(?:""[^"]*)*"|[^,]*),/g);

Text::CSV_XS を使って以下のようにすることもできる。日本語を扱わないなら {binary=>1} は不要である。
use Text::CSV_XS;
$csv=Text::CSV_XS->new({binary=>1}); #create a object
$line='"北海道,札幌市",ABC,"XX,XX","""abc"""';
$status=$csv->parse($line);          #parse a string
@values=$csv->fields();              #get the fields
print join("\n",@values);
Text::CSV_XS は Active Perl なら標準で含まれているからこれが便利だろう。

投稿者 augustus : 2004年08月03日 22:36

トラックバック

このエントリーのトラックバックURL:
http://www.augustus.to/cgi-bin/blog/mt-tb.cgi/66

コメント

コメントしてください




保存しますか?