解決済みの質問
Excelのcsv形式の読み込み
前回、http://okwave.jp/qa/q6018540.htmlで
質問させていただきましたJurassic_periodです。
お力を貸していただきました方々本当にありがとうございました。
今回ですが同じプログラムでまた壁にぶつかってしまいました。
どうかよろしくお願いいたします。
Excelのcsv形式の「file.csv」のようなデータを読み込んでいます。
「out.csv」のように出力したいのですが
未入力「""」のデータ箇所が多々ある事に気が付きました。
次データを読み込むため出力データがズレてしまい困っています。
「file.csv」
"2010/1/1","C","こんにちは","田中","end",
"2009/10/2","B","おはよう","","end",
"2007/3/20","E","Good mor
ning","佐藤","end",
"1988/8/16","","こんばんは","中
村","end",
"","A","Hello","木村","end",
"2005/9/17","D","おはようご
ざいます","斎藤","end",
「out.csv」(このように出力したいです)
C,こんにちは,田中,2010/1/1,end,
B,おはよう, ,2009/10/2,end,
E,Good morning,佐藤,2007/3/20,end,
,こんばんは,中村,1988/8/16,end,
A,Hello,木村, ,end,
D,おはようございます,斎藤,2005/9/17,end,
解決法として、正規表現を用いて「半角スペース」を入れようとしました。
また、直接「file.csv」の「,"",」を置換で「," ",」にしましたが
基データを操作するのは好ましくないのでプログラムで
どうにか処理ができないでしょうか。
「今書いているプログラムです」
#!/usr/local/bin/perl
use strict;
use Fatal qw/ open /;
my $csv_file = "file.csv";
my @csv;
&readCsvFile($csv_file);
open(OUT,">out.csv");
for(my $i=0; $i<=$#csv; $i++){
$csv[$i][0] =~ s/"//; #行頭の"を削除
$csv[$i][4] =~ s/"//; #行末の"を削除
$csv[$i][0] =~ s// /; #空データを半角スペースに置換
$csv[$i][1] =~ s// /;
$csv[$i][3] =~ s// /;
print OUT $csv[$i][1],",";
print OUT $csv[$i][2],",";
print OUT $csv[$i][3],",";
print OUT $csv[$i][0],",";
print OUT $csv[$i][4],",\n";
}
close(OUT);
sub readCsvFile {
open(IN, $_[0]);
my $line = "";
while(<IN>) {
chomp;
$line .= $_;
next if $line !~ /end/;
push @csv, [ grep { length } split(/","|",|"/, $line) ];
$line = "";
}
close(IN);
}
どうか、よろしくお願いいたします。
投稿日時 - 2010-07-07 16:00:09
grep { length } が空要素を削除しています。grep { length } の処理を行わずに、行の先頭の " と行末の ", を別の手段で削除すれば空要素もそのまま残るようになります。
sub readCsvFile {
open(IN, $_[0]);
my $line = "";
while(<IN>) {
chomp;
$line .= $_;
next if $line !~ /end/;
$line =~ s/^"//; $line =~ s/",$//; # この行を追加
push @csv, [ split(/","/, $line) ]; # "," のみに戻す
$line = "";
}
close(IN);
}
投稿日時 - 2010-07-07 17:37:49
お礼
回答ありがとうございました。
無事に解決できました!
本当にありがとうございました!
投稿日時 - 2010-07-09 21:30:40
7人が「このQ&Aが役に立った」と投票しています
ベストアンサー以外の回答(4件中 1~4件目)
流儀が違うのでご参考になるかわかりませんが、たぶん期待した結果が得られると思うものを作ってみました。
--------------------------------------
#!/usr/local/bin/perl
open(WR_DATA,">out.csv");
open(RD_DATA, "file.csv");
while(my $line = <RD_DATA>){
$line .= <RD_DATA> while ($line =~ tr/"// % 2 and !eof(RD_DATA));
$line =~ s/(?:\x0D\x0A|[\x0D\x0A])?$/,/;
$line =~ s/\r\n|\r|\n//g;
my @csv = map {/^"(.*)"$/s ? scalar($_ = $1, s/""/"/g, $_) : $_}
($line =~ /("[^"]*(?:""[^"]*)*"|[^,]*),/g);
if($csv[0] eq ""){ $csv[0] = " "; }
if($csv[1] eq ""){ $csv[1] = " "; }
if($csv[3] eq ""){ $csv[3] = " "; }
my $sTmp = sprintf("%s,%s,%s,%s,%s,\n",$csv[1],$csv[2],$csv[3],$csv[0],$csv[4]);
print WR_DATA $sTmp;
}
close(RD_DATA);
close(WR_DATA);
exit;
投稿日時 - 2010-07-09 11:45:49
お礼
ralf124cさま、2回目の回答ありがとうございます。
ANo.3の回答を入れてプログラムを書いていただき
とても参考になりました。
こんな書き方があったのかと驚きました。
本当にありがとうございました。
投稿日時 - 2010-07-09 21:43:42
最近は閑古鳥が泣いている某サイトに昔ちょうどいい感じのお題が出ていました。
perlの投稿は2件。
べた書きされている方は、戻り読みとかすればもう少しスマートになりそうだけど
紹介しておきます。
Text::CSV_XSは日本語の扱いに問題があるって聞いたことあるけど
今はもう直っているのかな?
参考URL:http://ja.doukaku.org/33/
投稿日時 - 2010-07-08 23:17:58
お礼
こんなサイトがあったのですね!
参考にさせていただきました。
Text::CSV_XSを使用しようか悩みましたが、
問題があるとあちこちで書かれていたため結局やめました…
ありがとうございました。
投稿日時 - 2010-07-09 21:37:30
OKWaveのオススメ
おすすめリンク