• ベストアンサー

ファイルの読み込みと置き換え

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行くらいあります。 たぶん配列の入れるタイミングとか何かが間違っていると思うのですが、どこで間違っているのかがよくわかりません。 教えていただけると助かります。

  • Perl
  • 回答数5
  • ありがとう数6

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

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。 とりあえず、こんなところで。

tukikageran
質問者

お礼

ありがとうございます。 無事置き換えをすることが出来ました。 open(IN,"list.txt") || die "ファイルが見つからないので終了します。"; while(<IN>){ $_=~s/xls/エクセルファイル/; push(@file, "$_"); print "置き換え中!残りあと$count行です\n"; $count--; } close(IN); print"@file[18]","\n"; 可能であればなのですが、置き換え前に行数を知ることは出来ませんでしょうか。 文中にもカウントダウンの命令をいれてますが、当初は最初に@fileにいれていたので行数を変数に引き渡して取得してました。 しかし今回は行数を変数に引き渡せないのでカウントダウンにはならず-の数値が増えていく表示になりました。 ここをなんとかする方法はありませんでしょうか。

その他の回答 (4)

  • maura
  • ベストアンサー率46% (48/104)
回答No.5

なんだか混乱されているご様子なので 他の回答を、、 Perlでテキストファイルを読み込み、テキストの一部を置き換えをするというプログラム程度であれば、コマンド1行で可能です。 perl -ne 's/xls/エクセルファイル/; print' list.txt 結果が標準出力なので、ファイルに保存したいときは perl -ne 's/xls/エクセルファイル/; print' list.txt > save.txt とすると save.txt に保存されます

tukikageran
質問者

お礼

ありがとうございます。 一個の置き換えならば一行で出来ちゃうんですね。 今回はもうちょっと大きなプログラムの一部分をテストを兼ねながら作っていたのでfor文で作らせてもらいました。 一行変換は今後の為の知識として使わせていただきます。 ありがとうございました。

回答No.4

>可能であればなのですが、置き換え前に行数を知ることは出来ません >でしょうか。 >文中にもカウントダウンの命令をいれてますが、当初は最初に@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";

tukikageran
質問者

お礼

たびたびありがとうございました。 無事に取り込んだファイルの文字の置き換えができました。

  • kabaokaba
  • ベストアンサー率51% (724/1416)
回答No.3

こんな感じ ただし,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;

tukikageran
質問者

お礼

ありがとうございます。 @fileに入れた後にループさせる命令をwhileにしていたからだめだったんですね。 forにしたらうまくいきました。 事前に@fileにデータをわたし、行数をカウントして、その後for文で置き換えする方式にしました。 ありがとうございました。

  • maura
  • ベストアンサー率46% (48/104)
回答No.1

@file = <IN>; # ←配列に入れてる $count=@file; while(<IN>){ # これはもう何も取得できない @file を使用します while(@file){

tukikageran
質問者

お礼

ご回答ありがとうございました。 while(@file)は私も試してみたのですが、すると永遠にループから抜けなくなってしまいました。

関連するQ&A

  • ファイルの読み込み時について

    こんにちは。質問させてください。 あるファイルを読み込みその読み込んだ行に指定した文字列がふくまれていたら 別ファイルに書き込む処理を作成しています。 ------------------------------------- $count=0; $fd = fopen($file, "r"); //$file ベースとなるファイル if($fd){ while(!feof($fd)){ echo($count."\n"); <省略> if(指定した文字列発見){ 別ファイルに書き込む }   <省略> $count = $count + 1; } fclose($fd); } ------------------------------------- 念のため参照元ファイルの行を表示($countにて)させています。 ここで質問なんですが、 上記プログラムを実行すると$countが1703行までしか表示されません。 元データは10000行あります。 上記で10000行まで$countを表示できるはずなのですが・・・ 助けてください・・・ よろしくお願いいたします。

    • ベストアンサー
    • PHP
  • ファイルの書き込み

    以下のことがしたいです。 testフォルダよりテキストファイル達を読み込み、 ある行だけ取り除いたのちnewtestフォルダに書き出したいと思います。 以下、コードになります。 #!/usr/bin/perl $n_dir = "newtest/"; $b_dir = "test/"; opendir(DIR, $b_dir); while($file = readdir(DIR)){ $nfile="$n_dir$file"; $bfile="$b_dir$file"; if (-T $bfile) { open(IN, $bfile); #testフォルダよりファイルの読み込み @list = <IN>; close(IN); open(OUT,">$nfile"); #newtestフォルダに書き出し while(@list = <IN>) { #testフォルダ内のファイルを一行ずつ読み込み if (@list =~ /test/) { #行にtestという文字列があるぎょうだけ書き出し print OUT @list; } } close(OUT); } else{next;} } closedir(DIR); ということをやりたいのですが、 書き出されるファイルは空です。 どこが間違っているのでしょうか。 エラーなどは特にありません。 testフォルダのファイル達が そのままnewtestフォルダに書き出されるのですが、 中身は空です。 ご協力お願いします。

    • ベストアンサー
    • Perl
  • csvファイルチェック

    いつもここで勉強させていただいています。 初めてPHPプログラムを書くことになって本をみてここの サンプルをみながらやっていく途中でどうしてもうまくいかないので皆さんの知恵をお借りしたいと思います。 <HTML> <?php //行番号表示 $leng = 0; $file_name = "roba.csv"; //区切り記号 $kigou = ","; //指定項目数 $count_koumoku = 20; // 関数呼び出し $e = koumokuCheck($file_name,$kigou,$count_koumoku); print "--;>チェック終了"; function koumokuCheck($file_name,$kigou,$count_koumoku){ $file = fopen($file_name, "r"); while ($data = fgetcsv($file, 1000,$kigou)) { //項目数カウントする $num = count ($data); if( $num != $count_koumoku) { //項目数カウントする(指定項目数より小さい場合メッセージ表示) $leng++; print "-->$leng"."<--項目数が足りてません <br>\n"; } else { $leng++; } } flock($file,LOCK_UN); fclose($file); } ?> </HTML> 上記のようなチェック機能をつくりましたが結果は一つの循環で結果(N行目が項目数が足りない)を返してくれますがここを配列を利用して項目数が足りない行番号を覚えさせて最後に足りない行番号を列挙して一つの行にまとめて表示したい(例:1,3,6,7,9の項目が足りません)と思っていますがなかなかうまくいきません!みなさんのよいアドバイスをまっています。

    • ベストアンサー
    • PHP
  • 正規表現での置き換え

    正規表現で取り込んだテキストファイルの置き換えをしようとしています。 テキストファイルには Vol:down1b (Vol:down1b (F:\download1\sampledata))\sample.jpg Vol:down1b (Vol:down1b (F:\download1\sampledata))\sample2.jpg と入ってます。 Perlのプログラムでは $moto = "Vol:down1b (Vol:down1b (F:\download1";#1の置き換え元 $ato = "down1";#1の置き換え後 $moto = quotemeta($moto); open(IN,"list.txt") || die "ファイルが見つからないので終了します。"; @file=<IN>; for(@file){ $_=~s/$moto/$ato/; } close(IN); print"@file[10]","\n"; と書きましたが、なぜか置き換えがうまくいきません。 $moto変数の中にある(とかの文字があるのがだめなのでしょうか? quotemeta関数でエスケープはつけてるつもりですが・・・ 教えてください。よろしくお願いいたします。

    • ベストアンサー
    • Perl
  • ファイルの読込

    ファイルからテキストデータを読み込むときにCStdioFileクラスのReadStringを使って一行ずつ読み込んでいますが、指定した行だけを読み込めるようにしたいのですがどうしたらいいでしょうか?

  • textファイルについて

    あるディレクトリーに test.txt aaa.txt があるのですが、 二つのテキストを開いて もし text.txtの3行目に http://www.goo.ne.jp/ があり aaa.txtの10行目にも http://www.goo.ne.jp/ があるとすれば aaa.txtの10行目を消したいのですが、 そんな事って可能ですか?? 色々考えたのですが、aaa.txtの10行目を消す時に 10行目を空にすると言う指定が出来なくて困ってます。 どうしてもaaa.txtの削除が出来ません。 参考までにスクリプトを載せておきます <?php $file_name = array("aaa.txt", "test.txt"); $list = fopen($file_name[0], "a+"); $delete_list = fopen($file_name[1], "r"); $listfile = file($file_name[0]); $listmax = count($listfile); $listfile = file($file_name[1]); $delete_listmax = count($listfile); if ($delete_listmax > 0){ for ($delete_line = 1; !feof($delete_list); $delete_line++){ $delete_lines = fgets($delete_list); $delete_lines = trim($delete_lines); if ($delete_lines){ if (is_file($file_name[0])){ for ($line = 1; !feof($list); $line++){ $lines = fgets($list); $lines = trim($lines); if ($lines){ if ($delete_lines == $lines){ //ここの部分がわからないです fputs($list, "あああ"); echo "O,K\n"; } } } } } } } fclose($delete_list); fclose($list); echo "\n終了\n"; ?> 詳しい方がいましたら宜しくお願いします

    • ベストアンサー
    • PHP
  • C言語を使って、ファイルの読み込みをして切り出して2次元配列に格納した

    C言語を使って、ファイルの読み込みをして切り出して2次元配列に格納したいのです。 1,2行目に配列の行の数と列の数が書かれ、3行目から改行とカンマ、スペースで区切られて配列が書かれているテキストを読み込んで2次元配列に格納する。 テキストの例) 4 3 1.1 1.2 1.3 1.4 1.5 2.1 2.2 2.3 2.4 2.5 3.1 3.2 3.3 4.4 3.5 というプログラムを書いています。色々と参考書やサイトを参考してとりあえずの形にはなったと思ったのですが、実行してもエラーが出ます。 どこまで動いているか調べたところ、一行ごとに読み出してそれを切り出して行くところでおかしな事をしてしまっているようですが、どう変えたらいいものか分かりません。 なので、その点のアドバイスと 大きさの分からないファイルから1,2行目を読み出すのはこれで変な動きをする恐れはないか の2点についてヒントでも構わないので、教えてください。 以下、書いたソースです(申し訳ないのですが、文字数の関係で一部省略しています。) #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char *argv[] ) { double ** mainhairetu; int size_x, size_y; /* size_x 行 size_y 列 */ int i,j,count=0,count2; int *cut,*temp2; double temp; char s2[] = " ,"; char gyou[10],*num; FILE *fil; while((fgets(gyou,10,fil)) !=NULL){ if(count == 0){ size_x=atoi(gyou); count++; }else if(count ==1){ size_y=atoi(gyou); count=count+1; }else{ break; } } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ここでmallocを使ってcutとmainhairetuの2つの配列を作っています。 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ count=0; for (i = 0; i < size_y+2; i++) { mainhairetu[i][0] = atof( strtok( fgets(cut,50,fil),s2 ) ); for (j = 1; j < size_x; j++){ if(count <=1){ count++; break; }else{ mainhairetu[i][j] = atof( strtok( NULL,s2 ) ); } } } for(i=0;i<size_y;i++){ for(j=0;j<size_y;j++){ printf("%f",mainhairetu[i][j]); } printf("\n"); } return(0); }

  • htm.ファイルから冒頭の一行だけを読み込むには

    Perl 初心者です。 過去ログのNo.285625 にもありましたが、ファイルの内容を一括して配列@xxに読み込んでprint "$xx[0]\n" とやっても一行目が表示されません。読み込みたいファイルはhtmファイルで一行目には<BR>で改行が入っているのですが、この一行が読めません。どうしたらよろしいのでしょうか?初歩的な質問で済みませんが、お願いします。

    • ベストアンサー
    • Perl
  • 一行だけ読込

    Perlでのファイルの読込なんですが、 open(IN,"A.txt"); while ($xx = <IN>) { print $xx;} close(IN) とするとA.txtファイルの読込をするんですよね? A.txtの中の一行だけを読込むというのはできるんでしょうか? (10行あったら5行目を読込み、という感じです。)

    • ベストアンサー
    • Perl
  • ファイル読み込み・書き込み

    下記のようにtestディレクトリ内のファイルを読み込み、 それぞれにあるデータを足して、 読み込んだファイルを他のディレクトリに書き出したいのですが、 どのようにしたらよいのでしょうか。 とりあえず、下記はファイルを読み込んで、 なにも足さずそのまま別のディレクトリに移すとこまで、 やりたいと思っていますが、 どうやっていいものか・・・ #!/usr/bin/perl $dir = "test/"; opendir(DIR, $dir); while($file = readdir(DIR)){ open(IN, ">>$dir$file"); @list = <IN>; foreach $dataLine(@list) { print IN $dataLine; } close(IN); } closedir(DIR); ようはファイルに追記したいのですが、 上書きしないで、バックをとっておき、 別のところへ追記したバージョンを生成したいということです。 ご協力お願いします。

    • ベストアンサー
    • Perl

専門家に質問してみよう