• ベストアンサー

ファイルの書き込み

以下のことがしたいです。 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
  • 回答数4
  • ありがとう数3

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

  • ベストアンサー
  • shimix
  • ベストアンサー率54% (865/1590)
回答No.2

ついでに、もうひとつ   while(@list = <IN>) @listは配列になってしまいますよね?「testのある行だけskip」なら、この配列から1行単位で取り出して、その行をチェックすることになると思います。   @list = <IN>;   foreach $line (@list) {     if ($line =~ /test/) { #行にtestという文字列があるぎょうだけ書き出し     print OUT $line;     }   }    あ、書いちゃった・・。でもPerlは普段書いていないからミスがないかチェックしてくださいね(汗

trfnc223
質問者

お礼

一配列一行だと思ってました! ご回答ありがとうございました。 試してみます!

その他の回答 (3)

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.4

>配列の検索はできないのですね。。。 ある配列で、ある条件を満たす(満たさない)要素だけ取り出したい/取り除きたいということなら grep という関数が使えますよ。 >if (@list =~ /test/) { #行にtestという文字列があるぎょうだけ書き出し test というのが含まれるものだけ残すというのであれば、 @filterd = grep {/test/} @list; という感じです。 一度にフィルタリングしてしまうか、1行1行チェックしながら 出力するかどうかはまあ好みの問題ですのでお好きに。 #細かいこというとメモリの使用量とかありますけどね。

trfnc223
質問者

お礼

ありがとうございます! 試してみます。

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.3

if (-T $bfile) { open(IN, $bfile); #testフォルダよりファイルの読み込み @list = <IN>; close(IN); ↑これで、ファイルの内容を @list に取り出して、IN もcloseしちゃってるのに while(@list = <IN>) { #testフォルダ内のファイルを一行ずつ読み込み はいかんでしょう。 @list はここで空になってしまうので、出力に何も出てこない。 という結果になっているわけです。 あと if (@list =~ /test/) { #行にtestという文字列があるぎょうだけ書き出し これも期待通りには動きません。

trfnc223
質問者

お礼

本当ですね。 空のわけです。 ご回答ありがとうございました。 配列の検索はできないのですね。。。

  • shimix
  • ベストアンサー率54% (865/1590)
回答No.1

デバッグの手順として、   if (@list =~ /test/) { #行にtestという文字列があるぎょうだけ書き出し   print OUT @list;   } このifを外して   print OUT @list; だけにしたら、全部書き出されるかどうかを確認してください。それで書き出されれば   (@list =~ /test/) について「だけ」考えればいいです。

関連するQ&A

  • ファイルの書き込み2

    またまた失礼します。 やりたいことは以下です。 1.ディレクトリを開く。 2.ファイル達を読み込み。 3.追記用のデータファイルを開く。 4.「2」にデータを追記 5.別のディレクトリに書き出し。 以上です。 4番がうまくいきません。 ためしに4の工程を抜かすと問題なく書き出されます。 4の工程でやりたいことは、 1.タブ区切りのテキストファイルを読み込み。 2.書き出し用に読み込んだ(追記したいファイル)<productのpath="[ココの値!]"を取得。 3.「2」番で取得した値と「1」番で取得した値を比較。 4.「3」がtrueの行を追記して書き出し。 以上。 要するになにがしたいかというと、 仮にタブ区切りテキストには10行分のデータがあるとします。 それぞれの行には3つ分の値が入っており、先頭にIDが付いています。 一番最初に読み込んだファイル(追記したいファイル)にも同様にIDが振られており(<product path="ココ")そのIDとタブ区切りテキストのIDが一致した行だけ追記したいということです。 下記のコードだとなぜか、 10行分のデータがすべて追記されてしまいます。 コードは以下です。 #!/usr/bin/perl #既存ファイル読み込み&追記 $n_dir = "newXml/"; $b_dir = "xml/"; opendir(DIR, $b_dir); while($file = readdir(DIR)){ $bfile="$b_dir$file"; $nfile="$n_dir$file"; $dfile="data/data.txt"; if (-T $bfile) { open(IN, $bfile);#既存ファイルオープン @list = <IN>; close(IN); open(OUT,">$nfile");#書き出しファイルオープン foreach $line (@list) { if ($line =~ /\<product/){ $line =~ /path=\".*\"/;#path取得 $1; } if ($line =~ /\<\/product\>/) { open(IN, $dfile);#追加データファイルオープン while($data = <IN>){ chomp(@data = split(/\t/,$data)); $data[0] =~ s/\//_/g; if($data[0] == $1){#取得したパスとdata.txtとってきた値を比較 print OUT <<EOF; <ds path="$data[0]">$data[1]</ds> <kw>$data[2]</kw> $line EOF } else{next;} } close(IN) }else{print OUT $line;} } close(OUT); } else{next;} } closedir(DIR); 長々と申し訳ありません。 エラーなどは特にありません。 ご協力お願いします。

    • ベストアンサー
    • 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
  • ハッシュを使った集計結果の出力について

    ハッシュを使った集計結果の出力について testフォルダに以下のファイルがあるとします。  aaa_1、aaa_2、bbb_1、bbb_2、ccc_1、・・・ 各ファイルには○△×がついた行があり、 「aaa」のファイル(aaa_1とaaa_2)の○△×の数、「bbb」のファイルの○△×の数、を集計したいと思っています。 出力イメージは以下です。  ファイル名の一部,○の数,△の数,×の数  aaa,13,59,37 ファイル名の一部をキーとして、 ○△×の回数を値にしたハッシュで集計しようとしましたが、 以下のようになってしまいました。 ,0,0,0 ,0,0,0,0,0,0 aaa,13,59,0 aaa,13,59,0,13,59,37 bbb,20,10,0 bbb,20,10,0,20,10,30 ハッシュが十分に分かっていないので、おかしなことをしてるのだと思うのですが。。 ご教授くださいますよう、お願いします。 opendir(DIR, $dir); while ($file = readdir(DIR)){  $maru =0;  $san =0;  $batu =0;  $file =~/(.*)_(.*)/;  $name = $1;  open(IN, "$dir/$file");   while ( $line = <FIN1> )   {    chomp( $line );    if($line =~/○/){      $maru++;    }elsif($line =~/△/){      $san++;    }elsif($line =~/×/){      $batu++;    }  } push(@{$test{$name}} , $maru,$san,$batu); @gyou = ( $name , join ("," , @{$test{$name}})) ; print OUT join (",", @gyou). "\n"; } close (IN); close (OUT);

    • ベストアンサー
    • Perl
  • ログファイルの指定行に書込み

    open(IN,"$log") || &error("Open Error"); @data = <IN>; close(IN); while (100 <= @data) { pop(@data); } open(OUT,">$log") || &error("Write Error"); print OUT "$in{'id'}<>$in{'comment'}\n"; print OUT @data; close(OUT); ログにはID、時間、コメントが登録されています。 送信データの中に、ログに登録済みのIDがある場合には、そのIDのある行のみを書き換えたいのですが、方法がどうしてもわかりません。 $logに記録されるIDの順番は以下のようにランダムです。IDに登録される文字列は1からの数値のみです。 52<>コメント 120<>コメント 35<>コメント 8<>コメント 2<>コメント 19<>コメント 85<>コメント よろしくお願いいたします。

    • ベストアンサー
    • Perl
  • ファイルの入出力2

    指定したフォルダ内にあるcsvファイルのデータを 指定したhtmlファイルに出力するプログラムを書いているのですが、 下記のままだとcsvファイルにあるすべてのデータをとってきてしまいます。実現させたいことは「指定したフォルダ内にあるcsvファイル2行目のデータだけファイル出力する」というものです。 どなたかご協力お願いします。 #!/usr/bin/perl #--------------------------------------------------------------# # ディレクトリを開く #--------------------------------------------------------------# opendir(DIR,"test/"); #--------------------------------------------------------------# # 出力ファイル名を指定 #--------------------------------------------------------------# $dest = "test.html"; open (OUT, ">$dest") or die "$!"; #--------------------------------------------------------------# # 出力ファイルにhtmlを出力 #--------------------------------------------------------------# print OUT '<html> <head> <title>無題ドキュメント</title> <style type="text/css"> <!--.style1 {color: #FFFFFF}--> </style> </head> <body> <table width="419" height="105" border="0" cellpadding="0" cellspacing="0"> <tr> <th bgcolor="#000000"><span class="style1">名前</span></th> <th bgcolor="#000000"><span class="style1">住所</span></th> <th bgcolor="#000000"><span class="style1">性別</span></th> </tr>'; #--------------------------------------------------------------# # ディレクトリにあるファイル名を取得 #--------------------------------------------------------------# while ($filename = readdir(DIR)) { # ディレクトリにあるファイルパスを取得 $path = "test/$filename"; if(-f $path) { # ファイルオープン open (IN, $path) or die "$!"; while (<IN>) { # カンマ区切りでデータを取得&改行削除 chomp(@data = split(/,/, $_)); print OUT "<tr>\n"; # 各行の3つのカンマ区切りデータを取得 print OUT "<th bgcolor=\"#666666\">",$data[0],"</th>\n<td>",$data[1],"</td>\n<td>",$data[2],"</td>\n"; print OUT "</tr>\n"; } close(IN); } } #--------------------------------------------------------------# # ディレクトリを閉じる #--------------------------------------------------------------# closedir(DIR); print OUT "</table> </body> </html>"; #--------------------------------------------------------------# # ファイルを閉じる #--------------------------------------------------------------# close(OUT);

    • ベストアンサー
    • Perl
  • ファイルの最後の行から表示させる(最新情報を5回分だけ表示)

    ファイルの最後に1行追加し、6行以上になるとファイルの先頭を1行削除。 表示は最後の行から行うスクリプトを作りたいのです。 新しい情報を5回分だけ表示する様にしたかったのですが、余りにも力技なのでもう少しスマートにやる方法を教えてもらえませんか? ----sort.txt---- 1a 2b 3c 4d ---------------- #!/usr/bin/perl $fname = "sort.txt"; print "Content-type: text/html;\n\n"; $aaa="5e"; open(OUT, ">>$fname"); flock(OUT, LOCK_EX); print OUT "$aaa\n"; flock(OUT, LOCK_NB); close(OUT); open(IN, "$fname"); $cnt = "0"; while($line = <IN>){ $a[$cnt] = "$line"; $cnt++; } close(IN); if($cnt > 5){ open(OUT, ">$fname"); flock(OUT, LOCK_EX); $cnt = "0"; while($cnt < 6){ if($cnt > 0){ print OUT "$a[$cnt]"; } $cnt++; } flock(OUT, LOCK_NB); close(OUT); } $cnt = "0"; open(OUT, "$fname"); @buff = <OUT>; close(OUT); foreach $line ( reverse @buff ){ $cnt++; print "$line<br>\n"; } exit();

    • ベストアンサー
    • Perl
  • ファイルの読み込みと置き換え

    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
  • phpでディレクトリにあるファイル数を知るには?

    こんにちわ, 今phpであるディレクトリ以下のファイルをすべて,リスト(select)で表示したいのですが,そのフォルダにいくつファイルがあるかを知りたいのです。 $d = dir("/HOGEHOGE"); echo "<select name=\"file\" size=??? multiple>"; while($entry=$d->read()) {   echo "<option value=\"$entry\">$entry"; } $d->close(); 上記のことで???にそのファイルを入れることができれば,それができると思うのですが,何かいい方法,またはそのようなファイル数を知る「ls|wc -w」のような方法があれば教えてください。 よろしくお願いします。

    • ベストアンサー
    • PHP
  • 配列の一部を書き換えてファイルに保存する方法は?

    $dicname ='GermJ.txt'; open(IN, "$dicname"); @list = <IN>; close(IN); 読み込んだ配列@listの5番目のデータを'aaaaaaaaaa'に書き換えたいのですが、 $list[5]='aaaaaaaaaaaaaaaaa'; open(OUT, "> $dicname"); foreach (@list) { print OUT $_; } close(OUT); とやって、ファイルの中身を調べると、6番目の文字列データが5番目の文字列データの後ろにくっついてしまっています。 改行マークを $list[5]='aaaaaaaaaaaaaaaaa',\n;のように行末に追加しても、次の行とのあいだに空間が生まれます。基本的なファイル書き込みの知識をお尋ねして申し訳ありませんが,どうかお教えください。

    • ベストアンサー
    • Perl
  • レコードの書込み判断

    ファイルを読込み、読込まれたレコードの39桁目が0であれば出力という判断を下記のコーディングに追加したいのですが、どのように記述すればよいでしょうか? if(open(OUT,">$year$mon$mday$csv")){  for my $fname (sort @dirs){   if(open(IN,"$fname")){   my @lines = <IN>;   print OUT @lines;   close(IN);   }  }  close(OUT); }

専門家に質問してみよう