challenge RFC 4180対応版 CSVレコードの分解

ある関数(splitCSV)に渡された文字列を配列に分解して列ごとに表示してください。
渡される文字列は、CSVデータの1レコードが設定されているとします。

使用するデータはK3形式が元になっている仕様で
エクセルが出力しているような形式です。

書式には次のような特徴があります。
1. 各レコードは「改行」によって区切られている。
2. 各列は「,」によって区切られている。
3. 列のデータは「"」によって囲んでも良い。
4. 列に「,」「改行」「"」いずれかを含む場合「"」で
   囲わなければならない。
5. 列データに「"」を含める場合「""」とする。

本来、改行コードはCRLFですが今回は特に指定しません。

次の入力があった場合
"aaa","b
bb","ccc",zzz,"y""Y""y",xxx

出力は
1 => aaa
2 => b
bb
3 => ccc
4 => zzz
5 => y"Y"y
6 => xxx

となります。
このお題はraynstardさんの投稿によるものです。ご投稿ありがとうございます。助かります。

Posted feedbacks - PHP

一旦','で分割してしまってから'"'が奇数個含まれるフィールドに偶数になるまで後ろのフィールドを繋ぎ直す様な感じでやってみた。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
function splitcsv($line){
  $r=array();
  $a=explode(",",$line);
  while(list(,$v)=each($a))
  { if(strpos($v,'"')!==false)
    { while(substr_count($v,'"')&1)
      { if(!(list(,$v1)=each($a)))
          return false;
        $v.=','.$v1;
      }
      ereg('"(.*)"',$v,$regs);
      $v=str_replace('""','"',$regs[1]);
    }
    $r[]=$v;
  }
  return $r;
}

$line='"aaa","b
bb","ccc",zzz,"y""Y""y",xxx';

print_r(splitcsv($line));
?>

PHP 入出力ストリームと fgetcsvを使って簡単にやってみた

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<?php
function csv2array($csv)
{
    $fp = fopen('php://temp/maxmemory:'.(5*1024*1024), 'r+');
    fputs($fp, $csv);
    rewind($fp);
    return fgetcsv($fp);
}

$csv='"aaa","b
bb","ccc",zzz,"y""Y""y",xxx';

var_dump(csv2array($csv));

Index

Feed

Other

Link

Pathtraq

loading...