この3日で作った下記のCSV関連ルーチンで簡単なプログラムを作ってみた。
・csv_load・・・CSVファイルから配列変数@csv_lineに読み込む
・csv_save・・・CSVファイルに@csv_lineの内容を書き込む
・csv_sort・・・指定の列で@csv_lineを並び替える
※プログラム初心者のため、このページのプログラムソースは正常に動作しない事がありますご注意下さい。
(あっちこっちのサイトの情報を寄せ集めてるので思わぬ不具合があるかも)
追加のサブルーチン
サンプルプログラムの前に、CSVファイルでは区切り文字の「,」と「改行」をデータとし扱えないので扱えるようにするサブルーチンを作ってみました。
処理的には使用頻度の低いと思われる文字「^」をシステム文字として、「^=^0」「改行=^1」「,=^2」のようにファイルや@csv_line中では右辺、表示する際は左辺というように変換処理をかけています。
・&csv_format_load(変換文字列)・・表示形式「^0→^」に変換します。
・&csv_format_save(変換文字列)・・保存形式「^→^0」に変換します。
上記は単一の文字列だけに作用するため@csv_lineを一括で処理できるように下記の2つも作りました。
・csv_split(行データ)・・行データを「,」ごと分解して「^0→^」処理をして配列変数を出力します。
・csv_join(配列変数)・・上で出力した配列変数を「^→^0」して、「,」区切りの行データに戻します。
#------------------------------------------------- # CSV形式で使えない「,」と「改行」をデコード(元に戻す「^0→^」) #------------------------------------------------- sub csv_format_load{ my($r)=$_[0]; $r =~ s/\^2/,/g; $r =~ s/\^1/\n/g; $r =~ s/\^0/\^/g; return($r); } #------------------------------------------------- # CSV形式で使えない「,」と「改行」をエンコード(変換する「^→^0」) #------------------------------------------------- sub csv_format_save{ my($r)=$_[0]; $r =~ s/\^/\^0/g; $r =~ s/\x0D\x0A/\^1/g; $r =~ s/\x0D/\^1/g; $r =~ s/\x0A/\^1/g; $r =~ s/,/\^2/g; return($r); } #------------------------------------------------- # CSV形式の行データをデコード+splitして、連想配列を返す #------------------------------------------------- sub csv_split{ my($u)=$_[0]; my(@s)=split(/,/,$u); my($i); if ($u =~ /\^/){ for ($i = 0; $i <= $#s; $i++){ $s[$i]=&csv_format_load($s[$i]); } } return(@s); } #------------------------------------------------- # CSV形式のセルデータをエンコード+joinして、文字列を返す #------------------------------------------------- sub csv_join{ my(@s)=@_; my($r,$i); for ($i = 0; $i <= $#s; $i++){ $s[$i]=&csv_format_save($s[$i]); } $r=join(",",@s); return($r); } #-------------------------------------------------
サンプルプログラム
・どんな動きをしているか自分で確認するために作ったので、わかりにくくて申し訳ありません。
動作概要
・CSV形式の「test.csv」からデータを読み込み、何か処理を行った上で「test2.csv」に保存し、再度「test2.csv」を開き保存できているか確認するプログラムです。
・プログラムはブラウザにHTML形式で出力します。
・4つの処理を行っています。
注意点
・特に難しい事はしてないのでパーミッションの設定などは普通で動くはずです、行頭のPerlのパスは各自環境にあわせて書き換えが必要です。
#!/usr/local/bin/perl #上は各自の環境にあわせる事 local($csv_line); my($html,$i,$j,@csv); $html.="<h1>CSV関連のサンプルプログラム1</h1>"; $html.="<a href=\"?m=1\">test.csvを読み込・何もせず・保存する</a><br />"; $html.="<a href=\"?m=2\">数字降順で並び替えて保存する</a><br />"; $html.="<a href=\"?m=3\">ふりがな昇順で並び替えて保存する</a><br />"; $html.="<a href=\"?m=4\">ふりがな降順で並び替えて保存する</a><br />"; $html.="<a href=\"?m=5\">一部書き換えて保存する</a><br />"; #- - - - - - - - - - 読み込み - - - - - - - - - - $html.="<hr />ファイルから読み込んだ内容<br />"; &csv_load("test.csv"); for ($i = 0; $i <= $#csv_line; $i++){ @csv=&csv_split($csv_line[$i]); $csv[4] =~ s/\n/ 改行 /g; #改行の可視化 $html.="$csv[0] | $csv[1] | $csv[2] | $csv[3] | $csv[4] <br />"; } #- - - - - - - - - - 処理の分岐 - - - - - - - - - - if ($ENV{'QUERY_STRING'} eq "m=2"){ $html.="<hr />処理:数字降順でソート &csv_sort(\"9\",0);<br />"; &csv_sort("9",0); }elsif ($ENV{'QUERY_STRING'} eq "m=3"){ $html.="<hr />処理:ふりがな昇順でソート &csv_sort(\"a\",2);<br />"; &csv_sort("a",2); }elsif ($ENV{'QUERY_STRING'} eq "m=4"){ $html.="<hr />処理:ふりがな降順でソート &csv_sort(\"z\",2);<br />"; &csv_sort("z",2); }elsif ($ENV{'QUERY_STRING'} eq "m=5"){ $html.="<hr />処理:伊藤三太の行を変更して保存;<br />"; @csv=&csv_split($csv_line[3]); $csv[1]="伊藤三太郎"; $csv[2]="いとうさんたろう"; $csv[4]="記号のテスト\n,^です"; $csv_line[3]=&csv_join(@csv); #csv_split後は記号など普通に使用でき、csv_joinで行データに戻せる。 }else{ $html.="<hr />処理:なにもしない<br />"; } #- - - - - - - - - - 処理の確認 - - - - - - - - - - for ($i = 0; $i <= $#csv_line; $i++){ @csv=&csv_split($csv_line[$i]); $csv[4] =~ s/\n/ 改行 /g; #改行の可視化 $html.="$csv[0] | $csv[1] | $csv[2] | $csv[3] | $csv[4] <br />"; } #- - - - - - - - - - 書き込み - - - - - - - - - - &csv_save("test2.csv"); #- - - - - - - - - - 書き込みの確認 - - - - - - - - - - &csv_load("test2.csv"); $html.="
保存したファイルの内容の確認
"; for ($i = 0; $i <= $#csv_line; $i++){ @csv=&csv_split($csv_line[$i]); $csv[4] =~ s/\n/ 改行 /g; #改行の可視化 $html.="$csv[0] | $csv[1] | $csv[2] | $csv[3] | $csv[4] <br />"; } #- - - - - - - - - - 結果表示 - - - - - - - - - - print "Content-type: text/html\n"; print "\n\n"; print "<html>"; print "<head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"></head>"; print "<body>$html</body>"; print "</html>"; exit; #以下に 今回の csv_format_load / csv_format_save / csv_split /csv_join と # 前回と前々回の csv_load / csv_save / csv_sort のルーチンを追加する事
下記はtest.csvとして保存して下さい。(文末の改行あっても無くても問題ありません。)
1,山田太郎,やまだたろう,男,記号「^0」 2,鈴木一美,すずきかずみ,女,記号「^1」 3,山田花子,やまだはなこ,女,記号「^2」 4,伊藤三太,いとうさんた,男,記号「^0」「^1」「^2」 5,田中浩二,たなかこうじ,男,記号「^0^0^1^1^2^2」