*[[CSVのパース]] [#gfbcf769]
#contents
**面倒い問題 [#h800f230]
-CSV のパースは一見簡単だがダブルクオートで囲った形式も扱おうとすると厄介な問題である。
-毎回悩むのでここにパース用関数をメモっておく。

**パース関数の実装 [#k5700d98]
ここでは以下の条件を満たす形式の CSV を対象とします。
((エクセルのCSV吐き出しの形式がこれのようです。))
-区切りはカンマである。
-データにカンマを含む場合はダブルクオートで囲う。
-ダブルクオートで囲ったデータ中のダブルクオートはダブルクオート2回で置き換える。

***PHP版 [#ied8f9c8]
 /**
  * CSV の1行をパースします。
  * この関数が対応しているCSVの行形式は以下の通りです。
  * ・区切りはカンマである。
  * ・データにカンマを含む場合はダブルクオートで囲う。
  * ・ダブルクオートで囲ったデータ中のダブルクオートはダブルクオート2回で置き換える。
  *
  * @return CSV をパースした結果の配列
  */
 function parse_csv($line) {
 	preg_match_all('/("[^"]*(?:""[^"]*)*"|[^,]*),?/', $line, $a);
 	foreach($a[1] as $key => $value) {
 		if(preg_match('/^"(.*)"$/', $value, $value2)) {
 			$a[1][$key] = preg_replace('/""/', '"', $value2[1]);
 		}
 	}
 	return $a[1];
 }
実行例
 $line = 'hdjks,d"as,"a,a","b""b",d,';
 print_r(parse_csv($line));


***Perl版&aname(perl); [#a6d77347]
 #
 # CSV の1行をパースします。
 # この関数が対応しているCSVの行形式は以下の通りです。
 # ・区切りはカンマである。
 # ・データにカンマを含む場合はダブルクオートで囲う。
 # ・ダブルクオートで囲ったデータ中のダブルクオートはダブルクオート2回で置き換える。
 # 
 # @return CSV をパースした結果の配列
 #
 sub parse_csv() {
     my $line = shift();
     my @a = ();
     while($line =~ /("[^"]*(?:""[^"]*)*"|[^,]*),?/g) {
         $_ = $1;
         s/^"(.*)"$/$1/ && s/""/"/g;
         push(@a, $_);
     }
     if($columns[-1] eq '') {
         pop(@a);
     }
     return @a;
 }
実行例
 $line = 'hdjks,d"as,"a,a","b""b",d,';
 print join("\n", parse_csv($line));


*コメント [#c64554f5]
- 重宝します ありがとう -- [[のあん]] &new{2007-11-22 (木) 10:17:48};
- なるほど、なろほど。 勉強になります。 -- [[ゴリ]] &new{2007-11-24 (土) 21:01:56};
- PHP の場合、fgetcsv を使うという手も。日本語コード処理で多少難有ですが。 -- [[通りすがり]] &new{2009-09-11 (金) 10:42:27};
- EGkxnymGGfYAHNER -- [[adqnhhgm]] &new{2009-09-12 (土) 12:01:06};

#comment


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS