- ベストアンサー
ファイルの読み込みと置き換え
Perlでテキストファイルを読み込み、テキストの一部を置き換えをするというプログラムを作っています。 用意されているテキストファイルは複数行あるもので、リスト作成ツールのフリーソフトにより作成されています。 目的はファイルを読み込み、一行一行中を見て特定の文字を置き換えて、最後に配列に一行一行いれていくというものです。 逆に配列に一度いれて一個一個置き換えてもOKで、結果が同じならばOKです。 以下にそのプログラムを書きます。 ############################## open(IN,"list.txt") || die "ファイルが見つからないので終了します。"; @file = <IN>; $count=@file; while(<IN>){ $_=~s/xls/エクセルファイル/; print "置き換え中!残りあと$count行です\n"; $count-- } close(IN); print"@file[18]","\n"; ############################## 最後の行で置き換えが成功したか見てますが、これを実行しても何も表示されません。 もちろん行数は18行どころか100行くらいあります。 たぶん配列の入れるタイミングとか何かが間違っていると思うのですが、どこで間違っているのかがよくわかりません。 教えていただけると助かります。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
open(IN,"list.txt") || die "ファイルが見つからないので終了します。"; @file = <IN>;← ここでlist.txt 全行を読み込んでしまっている… while(<IN>){ ← だから、ここのwhileループは通らない。読み終わっているので、<IN>がfalseになる。ゆえにwhileループの中の処理は通らない。 ゆえに、Openしてすぐwhileループに入らないとダメ。 open(IN,"list.txt") || die "ファイルが見つからないので終了します。"; while(<IN>){ このループで置き換え処理をして、結果を格納する配列へpush。 とりあえず、こんなところで。
その他の回答 (4)
- maura
- ベストアンサー率46% (48/104)
なんだか混乱されているご様子なので 他の回答を、、 Perlでテキストファイルを読み込み、テキストの一部を置き換えをするというプログラム程度であれば、コマンド1行で可能です。 perl -ne 's/xls/エクセルファイル/; print' list.txt 結果が標準出力なので、ファイルに保存したいときは perl -ne 's/xls/エクセルファイル/; print' list.txt > save.txt とすると save.txt に保存されます
お礼
ありがとうございます。 一個の置き換えならば一行で出来ちゃうんですね。 今回はもうちょっと大きなプログラムの一部分をテストを兼ねながら作っていたのでfor文で作らせてもらいました。 一行変換は今後の為の知識として使わせていただきます。 ありがとうございました。
- nyaa519323116
- ベストアンサー率51% (41/79)
>可能であればなのですが、置き換え前に行数を知ることは出来ません >でしょうか。 >文中にもカウントダウンの命令をいれてますが、当初は最初に@fileに >いれていたので行数を変数に引き渡して取得してました。 No.3さんのやり方がよいと思います。 簡易に書けば、こんな感じでしょうか。 open(IN,"list.txt") || die "ファイルが見つからないので終了します。"; @file=<IN>; close (IN); $count=$#file; <-- 読んだ行数をここで取得 my @out=(); <-- ワークの配列を空に初期化 for (@file){ $_=~s/xls/エクセルファイル/; push(@out, "$_"); print "置き換え中!残りあと$count行です\n"; $count--; } print"@out[18]","\n";
お礼
たびたびありがとうございました。 無事に取り込んだファイルの文字の置き換えができました。
- kabaokaba
- ベストアンサー率51% (724/1416)
こんな感じ ただし,Perl5.8で文字セットとエンコーディングとしては cp932(Windows/SJIS)を使用. use strict; use warnings; use Encode; use encoding 'cp932'; use Carp; my $code="cp932"; my $data_file = "bunsho.txt"; my $total_number_of_data_file; my $last_line; open my $data_fh, "<:encoding($code)" , $data_file or croak $data_file, " could not be opend.\n"; my @file = <$data_fh>; close $data_fh; $last_line = $total_number_of_data_file=@file; print $data_file, "は", $total_number_of_data_file, "あります\n"; for (@file) { s{xls}{エクセルファイル}g; print "残り", $last_line--, "行\n" } print @file;
お礼
ありがとうございます。 @fileに入れた後にループさせる命令をwhileにしていたからだめだったんですね。 forにしたらうまくいきました。 事前に@fileにデータをわたし、行数をカウントして、その後for文で置き換えする方式にしました。 ありがとうございました。
- maura
- ベストアンサー率46% (48/104)
@file = <IN>; # ←配列に入れてる $count=@file; while(<IN>){ # これはもう何も取得できない @file を使用します while(@file){
お礼
ご回答ありがとうございました。 while(@file)は私も試してみたのですが、すると永遠にループから抜けなくなってしまいました。
お礼
ありがとうございます。 無事置き換えをすることが出来ました。 open(IN,"list.txt") || die "ファイルが見つからないので終了します。"; while(<IN>){ $_=~s/xls/エクセルファイル/; push(@file, "$_"); print "置き換え中!残りあと$count行です\n"; $count--; } close(IN); print"@file[18]","\n"; 可能であればなのですが、置き換え前に行数を知ることは出来ませんでしょうか。 文中にもカウントダウンの命令をいれてますが、当初は最初に@fileにいれていたので行数を変数に引き渡して取得してました。 しかし今回は行数を変数に引き渡せないのでカウントダウンにはならず-の数値が増えていく表示になりました。 ここをなんとかする方法はありませんでしょうか。