- 締切済み
CSVデータの同じファイルに上書きするには。
CSV形式でデータdata.csvが書いてあります。プログラムを実行して、そのファイルの$data[4]の値が5という数字だった場合は、そこのセルだけ"解除"という文字に置き換えて(ほかに入ってる値ははそのまま)data.csvに上書きしたいのですが、どうもうまくいきません。したのように記述したのですが、どこが間違っているのかがわかりません。。どなたか教えてください。よろしくおねがいします。 #!/usr/bin/perl $file='data.csv'; open(FILE, "$file"); while(<FILE>){ @data = split(/,/, $_); } close(FILE); if($data[4] eq "5"){$data[4] = "解除";} open(OUT, ">$file"); print OUT @data; close(OUT);
- みんなの回答 (6)
- 専門家の回答
みんなの回答
- okiyoshi
- ベストアンサー率34% (11/32)
=notes -- BLUEPIXY さん wrote -- > 名前の書き換えができれば、 > もう一度読み出し書き出したりする必要はありません アドバイスありがとうございます。 確かに以下のほうがすっきりします。 でも、このページはインデントが効かないのでコードが読みづらいですね。 <td>に<pre>指定か何かをしてくれると有難いですが・・ と、これは管理人さんに言うことですね。 =cut ### 使用ファイル my $file_1 = "./test/date_1.csv"; my $file_2 = "./test/date_2.csv"; ### csvを編集しながら作業ファイルに書き出す open FILE_1, "<$file_1" or die( "can't open $file_1" ); open FILE_2, ">$file_2" or die( "can't open $file_2" ); while(<FILE_1>){ my @data = split /,/; $data[4] = '解除' if $data[4] eq '5'; print FILE_2 join( ',', @data ); } close FILE_1; close FILE_2; ### 作業ファイルを元のファイルにリネーム unlink $file_1; rename $file_2, $file_1;
- BLUEPIXY
- ベストアンサー率50% (3003/5914)
>でもwhileはループだから全部の行を読むまでループすると思っていました 全部の行を読みますが、その時その時の1行しか処理してないですよね、あとからまとめて書き出すつもりなら、全部の行をとっておかなくちゃね。 #3の方法は、一気にメモリに読み込む方法です。 ファイルが小さいかメモリに余裕があれば良い方法です。 ファイルの大きさが処理前にはわからないとか大きい場合は、 #4さんのように、一行ずつ処理して書き出して、 名前を書き換え元のファイルを消すのが常套手段になります。 (名前の書き換えができれば、もう一度読み出し書き出したりする必要はありません)
- okiyoshi
- ベストアンサー率34% (11/32)
=notes 単純なcsvファイルとして、どっこらしょとヒジョー!に単純に書 くとこうなりますでしょうか? csvの操作にはText::CSV_XSというモジュールが早くて便利です。 ・・標準モジュールではないのでDLする必要があります。 また、csvファイルをデータベースとして操作できるモジュールも ありますので調べて見てください。 =cut ### 使用ファイル my $file_1 = "./test/date_1.csv"; my $file_2 = "./test/date_2.csv"; ### csvを編集しながら作業ファイルに書き出す open FILE_1, "<$file_1" or die( "can't open $file_1" ); open FILE_2, ">$file_2" or die( "can't open $file_2" ); while(<FILE_1>){ my @data = split /,/; $data[4] = '解除' if $data[4] eq '5'; print FILE_2 join( ',', @data ); } close FILE_1; close FILE_2; ### 元のファイルに書き戻す open FILE_2, "<$file_2" or die( "can't open $file_2" ); open FILE_1, ">$file_1" or die( "can't open $file_1" ); while(<FILE_2>){ print FILE_1; } close FILE_2; close FILE_1; ### 作業ファイルを削除する unlink $file_2;
- BLUEPIXY
- ベストアンサー率50% (3003/5914)
#例えば、こんな風にすればいいです。 $file='data.csv'; open(FILE, "$file"); @data=<FILE>; close(FILE); for(@data){ @field = split /,/ ; $field[4] = "解除" if($field[4] eq "5"); $_=join(",",@field); } open(OUT, ">$file"); print OUT @data; close(OUT);
- BLUEPIXY
- ベストアンサー率50% (3003/5914)
while(<FILE>){ @data = split(/,/, $_); } では、@dataは、一行毎の処理ですから、一行分しか残りません だから >if($data[4] eq "5"){$data[4] = "解除";} は、最後のデータを作業しているだけで >print OUT @data; は、最後のデータしか出力しません
- hira6bg
- ベストアンサー率61% (8/13)
実行した後のdata.csvの内容はどうなっているのですか??
補足
お返事ありがとうございます。 例えば、CSVの各セルに 123456 123456 123456 123456 上のように数字が入ってるとします。1つの数字が一つのセルに入ってると思ってください。プログラムを実行すると同じファイルの 123456 123456 123456 123456 の4列目に5という数字が入っていたら”解除”という漢字におきかえたいのです。例は同じ数字が縦にならんでいますが、実際はランダム数字です。でじ¥、実行後は 1234解除6 1234解除6 1234解除6 1234解除6 となるように同じファイルに上書きしたいのです。 こういう感じですが、できますでしょうか?よろしくおねがいします。
補足
ありがとうございます。おっしゃるとおり、最後のデータしか上書きされませんでした。でもwhileはループだから全部の行を読むまでループすると思っていました。自分もwhileの部分があやしいなあと思っていました。全部の行を読み込むのにはどうしたらいいんですか?ほかに検討がつかなくって。。