• ベストアンサー

ファイルの最後の行から表示させる(最新情報を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();

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

  • ベストアンサー
  • arcsin
  • ベストアンサー率70% (28/40)
回答No.1

flockによる排他制御部分は省略します. #!/usr/bin/perl print "Content-type: text/html;\n\n"; my $fname = "sort.txt"; my $aaa = "5e"; my @list = (); #一旦配列に読み込み open(IN, "$fname"); @list = <IN>; close(IN); # 末尾に要素追加 push(@list, $aaa); # 6行以上なら先頭を削除 # $#list は配列の最後の添え字を表すので # $#list+1 は配列のサイズ = 現在の行数 if($#list+1 >= 6) { shift(@line); } #保存 open(OUT, ">$fname"); print OUT @list; close(OUT); #表示(@listの使いまわし) foreach(reverse @list){  print("$_<br>"); } exit; ----------- ですかね。一度配列に読み込んじゃってから追加削除操作をしたほうがスマートかなぁと思います。

meikenpochi
質問者

お礼

arcsinさん、回答ありがとうございます。 配列の方が分かりやすいですね、ありがとうございました。

その他の回答 (2)

回答No.3

微妙に気になるのですが、 データファイルは常に最大5行なのでしょうか? >新しい情報を5回分だけ表示する様にしたかったのですが は、例えば100行から5回分だけなのか、 それとも5行から5回分(つまり全部)なのかが気になります。 (別の方法でデータが増えたりするなどして) #一行追加と一行削除 push @list,$newline; shift @list if scalar(@list)>5; 色々あると思います。 $#data使ったりとか…。 #表示 foreach (reverse @list){   print "$_\n"; } ごく普通に? 仮に5行止まりでなくて例えば100行中5行表示だとしたら、 #表示 foreach (reverse @list[-5..-1]){   print "$_\n"; } とでもすることになるのでしょうか。 読みにくい気もしますけれど。 データ量が多くないのであれば、 一括で配列に読み込んで処理すると楽で、かつ読みやすいと思います。 あとはループ変数なるべく使わないようにすると 見た目がスマートに?見えるかもしれません。

meikenpochi
質問者

お礼

natsuki_tkさん、回答ありがとうございます。 >データファイルは常に最大5行なのでしょうか? 常に最大5行にする様にファイルを編集する様にしたいと思っています。一括で配列に読み込んで処理する方法が良いですね。

  • osamuy
  • ベストアンサー率42% (1231/2878)
回答No.2

最初から新しいものを先頭に置く形でsort.txtに書き込むようにしては。こんな感じ; use strict; use Fcntl qw( :flock ); sub rec($) { my $fname = 'sort.txt'; open( F, '+<'.$fname ) or die '?! ', $fname, ' - ', $!, ','; flock( F, LOCK_EX ) or die '?! ', $fname, ' - ', $!, ','; my @recs = <F>; pop @recs; seek( F, 0, 0 ) or die '?! ', $fname, ' - ', $!, ','; truncate( F, 0 ) or die '?! ', $fname, ' - ', $!, ','; print F $_[0]; print F @recs; close( F ) } 最初に、sort.txtに5行分空行をいれとく必要があります。ここの部分がちょっと危険な仕様と感じたなら適宜防衛してください。

meikenpochi
質問者

お礼

osamuyさん、回答ありがとうございます。 短くて、綺麗ですね。

関連するQ&A

専門家に質問してみよう