PERLのwhile構文についての質問

このQ&Aのポイント
  • PERLの勉強をはじめた初心者が、while構文の条件の記述方法について質問しています。
  • 質問文章にはサブルーチンの中でのwhile構文と、if文の中での-fという演算子の記述があります。
  • 質問者は超初心者であるため、詳しい解説を求めています。
回答を見る
  • ベストアンサー

極めて初歩的な質問ですみません

PERLの勉強をつい最近はじめました。 参考にしている本のどこを探してもみつからなかったので、質問させていただきます。 sub lock{ $c = 0; while (-f $lockfile) { $c++; if( $c >= 5 ){ print 'BUSY 少し時間を置いてもう一度登録してください。',"\n"; exit; } sleep(1); } open(LOCK,">$lockfile"); close(LOCK); というサブルーチンがありまして、分からないのはwhile構文の条件の記述です。 (-f $lockfile) とは、-fとは、どういう意味なのでしょうか。 if(! -f $mail01 ){ open(OUT,">$mail01"); close(OUT); というところにもありました。 どうぞ教えてやってください。超初心者なので、どうぞよろしくお願いします。

  • Perl
  • 回答数1
  • ありがとう数1

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

  • ベストアンサー
noname#4147
noname#4147
回答No.1

-f はファイル演算子の一つで、そのファイルが通常ファイルであれば真を返します。 ですので、while (-f $lockfile) は、 変数$lockfileに格納された名前のファイルが存在している間、ループすることになります。 ファイル演算子は非常に便利です。他にも以下のようなファイル演算子があります。 -r : 読み込み可能か否か -w : 書き込み可能か否か -x : 実行可能か否か -o : 自分のものか否か -R : 実uid/gidで読み込み可能か否か -W : 実uid/gidで書き込み可能か否か -X : 実uid/gidで実行可能か否か -O : 実uidのものか否か -e : 存在すれば -z : サイズが0か否か -s : サイズが0でなければ(ファイルサイズを返す) -f : 通常ファイルか否か -d : ディレクトリか否か -l : シンボリックリンクか否か -p : 名前付きパイプか否か -S : ソケットか否か -b : ブロック型スペシャルファイルか否か -c : キャラクタ型スペシャルファイルか否か -u : setuidビットが立っていれば -g : setgifビットが立っていれば -k : stickyビットが立っていれば -t : ファイルハンドルが tty としてオープンされていれば -T : ファイルがテキストファイルか否か -B : ファイルがバイナリファイルか否か

demo22nd
質問者

お礼

超初歩的な質問に答えていただきありがとうございました。私が参考にしている本に「ファイル演算子」についての記述はありませんでした。教えていただいた「ファイル演算子」でページ検索して今勉強しているところです。大変助かりました。 また初歩的な質問をすると思いますが、また教えてやってください。m(_._)m

関連するQ&A

  • ロックファイルの自動削除

    現在、以下のように記述されており、 ロックされてから2秒後に解除されるはずが 2秒後の最初の投稿の際にはロックファイルが存在している旨のメッセージが表示され、 (その際にロックファイルが自動削除されるが投稿はできない) その次の投稿から投稿が可能になるのですが、 2秒後の投稿の際にそのロックファイルを自動削除し、 投稿もできるようにするにはどのように書きかえたらいいのかお教えいただけませんか? ## --- ファイルロック sub lock { if ($_[0]) { $lock_file = $_[0]; } else { $lock_file = $lockfile; } if ($lock_file ne "") { local($flag) = 0; foreach (1 .. 5) { if (-e $lock_file) { sleep(1); } else { open(LOCK,">$lock_file"); close(LOCK); $flag = 1; last; } } if ($flag == 0) { $past_lock = -M "$lock_file"; if ($past_lock * 24 * 60 * 60> 2) { &unlock("$lock_file"); } &error("システムエラー","アクセスが集中しているため、タイムアウトとなりました。(ロックファイルが存在しています)"); } } } ## --- ファイルロック解除 sub unlock { if ($_[0]) { $lock_file = $_[0]; } else { $lock_file = $lockfile; } if (-e $lock_file) { unlink($lock_file); } }

    • ベストアンサー
    • CGI
  • ファイルロックについて

    以下のようなプログラムを作り実験しているのですが、よくわからない事態になっています。 まず、ブラウザを2つ用意して、一方のブラウザで実行した後、すぐに2つめのブラウザで実行します。 mkdirの場合、$which=1として、2つ目を実行すると、busyとでます。これは1つ目がロックしているからということは分かります。 しかし、symlinkの場合、2つ目でもbusyという文字はでず、何事もなかったように両方ともOKと表示されます。これは本当にロックできているのでしょうか。また、この場合、lock.cgiが生成されません。 また、サーバーによってはmkdirで試行すると、まだロックしていないにもかかわらず、busyとでるのもあります。これは、mkdir方式が対応していないと考えればよいのでしょうか。 ------------------------ #! /usr/local/bin/perl $lockfile = "./lock.cgi"; $which = 1; filelock(); sleep 10; fileunlock(); error("OK"); sub error{ print <<END; Content-type: text/html <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <HTML><HEAD> </head> <body> $_[0] </body></html> END exit; } sub filelock { if (-e $lockfile) { # 3分以上古いロックは削除する ($mtime) = (stat($lockfile))[9]; if ($mtime < time - 60) { fileunlock(); } } local($retry) = 2; if($which){ #mkdir関数式ロック while (!mkdir($lockfile, 0755)) { if (--$retry <= 0) { &error("busy"); } sleep(1); } }else{ # symlink関数式ロック if ($lockkey == 1) { while (!symlink(".", $lockfile)) { if (--$retry <= 0) { &error("busy"); } sleep(1); } } } } sub fileunlock { if($which){rmdir($lockfile);}else{unlink($lockfile); } }

  • ロックしたディレクトリが消えない(?)

    flock関数を使い、 $lockfile="./lock/lock.loc"; sub lock { foreach $i (1..6) { . . . if(open(LOCK,">$lockfile")){ if (flock(LOCK,6)) { $lock_flag = 1; last ; } } . . . } } という風にし、メインルーチンで&lockを実行し、ファイルロックしたのですが、flock(LOCK, 8)を使い忘れ、あとでFFFTPを使ってこれを消そうとしても、なにやらディレクトリが永遠に続いている感じになってしまい消せません。 /lock/lock.loc/lock.loc/lock.loc/lock.loc/lock.loc/... という風になっています。 それと元からlock/lock.locというディレクトリが存在したままflockを使ってしまったかどうかはちょっと確認していなかったのですが、使う前にあったとしたらlock.locはファイルではなく、ディレクトリです。 (mrdirを使ったロックなどをいろいろ試していたためです。) うまく説明できなかったのですが、どうすればこれは消せますか?後でflock(LOCK, 8)をやっても直りません・・ アップしたサーバーは@niftyです

    • ベストアンサー
    • 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
  • $retry--の「--」の意味は?

    $retry--の「--」の意味は? ファイルロックについて調べていたら function lock(){ //ロックファイル $file = "lock.txt"; $lockDir= "lock/"; $lockfile = $lockDir . $file; //再挑戦回数 $retry = 3; //30秒以上古いロックは削除する if (file_exists($lockfile)) { $mtime = filemtime($lockfile); if ($mtime < time() - 30) { unlock($file); } } //ロック用ディレクトリを作成する while (!@mkdir($lockfile, 0755)) { if ($retry-- <= 0) { print "只今混雑しています。";exit;} sleep(1); } } のコードを見つけました。「$retry--」の2回ハイフンでどんな意味なのでしょうか? ちなみに他に書き換えるとしたらどんなコードでかけるのでしょうか?

    • ベストアンサー
    • PHP
  • lockについて

    $file = 'file.log'; ------------------------------------ sub a{ &lock;ロック 1: open(IN, $file); # ファイルを開く 2: $count = <IN>; # カウンターを読み出す 3: close(IN); # ファイルを閉じる 4: $count++; # カウンターをひとつ増やす 5: open(OUT, "> $file"); # ファイルを開く 6: print OUT "$count\n"; # ファイルにカウンタを書き込む 7: close(OUT); # ファイルを閉じる 8: print "$count\n"; &unlock;ロック解除 } ------------------------------------ sub b{ 1: open(IN, $file); # ファイルを開く 2: $count = <IN>; # カウンターを読み出す 3: close(IN); # ファイルを閉じる } ------------------------------------ サブルーチンaではロック処理を行っていますが、 サブルーチンbでは書き込む処理がないためロック処理を行っていません。 読み込むファイルは同じでなのですが、 サブルーチンbにもロック処理を入れた方がいいのでしょうか?

    • ベストアンサー
    • Perl
  • クリックカウンタで隠しページにジャンプさせたい

    クリックカウンタについて教えて下さい。 (1)ある特定のカウント(例えば10)になったら隠しページに飛ばしたい (2)その後は何度クリックしてもカウント数はかわらない(動作させない) (3)その後カウントをクリアして再度クリックカウント出来るようにしたい (1)はなんとか出来ました。ですが、その後の動作が上手く出来ません。どなた様かアドバイスをお願い申し上げます。 <<click.cgi>> #!C:\Perl\bin\perl #=================================================== # 各種設定 #=================================================== $lockfile = "./lock"; $jumpurl = "./blog.html"; #ジャンプさせたい隠しページのURL $hikaku = 9; #日時の取得------------------------------ @youbi = ('日', '月', '火', '水', '木', '金', '土'); ($sec,$min,$hour,$mday,$mon,$year,$week,$yday,$sammer) = localtime; $year += 1900; $mon += 1; $yday = ""; $sammer = ""; $now = "$year年$mon月$mday日($youbi[$week]) $hour:$min-$sec秒\n"; #=================================================== # カウントアップ #=================================================== $url = $ENV{'QUERY_STRING'}; &lock; #ログファイルからデータの読み込み---------- open (IN,"<cntdata.dat") || die "Open Error!\n"; $cnt = <IN>; close IN; if($cnt >= $hikaku){ open (FILE, ">text.dat") || die "Open Error!\n"; print FILE "$now<br />10クリックを超えました。ご利用ありがとうございました。"; close FILE; open (OUT,">cntdata.dat") || die "Open Error!\n"; $cnt = 1; print OUT $cnt; close OUT; print "Location: $jumpurl\n\n"; exit; } #記録の更新-------------------------------- $cnt++; #カウントアップ $count = sprintf("%04d", $cnt); open (OUT,">cntdata.dat") || die "Open Error!\n"; print OUT $count; close OUT; &unlock; print "Location: $url\n\n"; #元のページにジャンプさせる exit; #=================================================== # エラーと排他処理サブルーチン #=================================================== sub lock { $retry = 3; if (-e $lockfile) { $locktime = (stat($lockfile))[9]; if ($locktime < time - 60) {&unlock;} } while (!mkdir($lockfile, 0755)) { if (--$retry < 0) {&error;} sleep(1); } } sub unlock {rmdir($lockfile);} <<cntdata.dat>> クリック数 <<text.dat>> 日時とありがとうメッセージ <<index.shtml>> <html> <head> <title>サンプル</title> </head> <body> <a href="./click.cgi?./index.shtml">クリック</a> <p>現在のクリック数:<!--#include file="./cntdata.dat"--></p> <p><!--#include file="./text.dat"--></p> </body> </html> 10クリック超えて、カウンタの数字が1に戻るのですが、その後またクリックすると動きません。なので、(3)にしたい場合には何をすればよいのでしょか。また(3)が無理なら(2)のようにクリックしてもcgiを動作しないようにしたいです。

    • ベストアンサー
    • Perl
  • PHPのファイルロックについて

    関数flock();について調べてたのですが、 結局、イマイチ使い所がわかりませんでした。 とりあえずCGIを手本として以下のロックを作ってみたのですが、 もし、flockを使うとしたらどのように使うのかアドバイスして欲しいと思っています。 ↓参考プログラム(echo部は進行を表示するためのもの) <?php define ("LOCK_FILE","./lock/lock.txt"); Lock(); Unlock(); //ロック function Lock(){ if(file_exists(LOCK_FILE)){ if(date(U) - filemtime(LOCK_FILE) > 30){ unlink(LOCK_FILE); echo("古いロック削除<br>"); } } $retry = 5; while(file_exists(LOCK_FILE)){ if($retry <= 0){ echo ("error<br>"); exit; } $retry--; sleep(1); } $lockfile = fopen(LOCK_FILE,"w"); fclose($lockfile); echo("ロック完了<br>"); } //アンロック function UnLock(){ unlink(LOCK_FILE); echo("ロック解除<br>"); } ?>

    • 締切済み
    • PHP
  • ファイルの配列のリストデータ(変数)の特定の変数の値だけを変えたい。

    サブルーチンの下のコードで表題の事をやろうとしていますが、 1)値が変わりません。($sinkou) 2)「エラー2','メッセージファイルが開けませんでした.」と表示されてしまいます。 3)モジュールで実現する方法がアったら教えてください。 よろしくお願いします。 sub SET_sinkou{ my($number,$name,$sinkou,@new,$line,$hanabi,$sinkou2); $lockfile = "$tmp_dir$cmd{'log'}\.lock"; &lock; if (!open(DB,$message_file)) { &Error('エラー1','メッセージファイルが開けませんでした.'); } while(<DB>){ ($number,$name,$sinkou) = split(/\t/,$_,3); if($number == $_[0] ) { $sinkou = $_[1]; $sinkou2 = $_[1]; #チェック用 $hanabi='花火'; #チェック用 $line=join(' ',$number,$name,$sinkou); push @new,$line; } else{ $line=join(' ',$number,$name,$sinkou); push @new,$line; } } close DB; if (!open(DB,">$message_file")) { &Error('エラー2','メッセージファイルが開けませんでした.'); } foreach(@new){ print DB $_; } close(DB); unlink($lockfile); &Html_head; print <<"EOF"; $body <h2><strong>変更しました。$sinkou=$sinkou=2=$_[0]=$_[1]=$hanabi</strong></h2><p> <!--$sinkou=$sinkou=2=$_[0]=$_[1]=$hanabiは値のチェック用--> </body></html> EOF }

    • ベストアンサー
    • Perl
  • flockについて

    http://www.freespace.jp/phpstudy.php4 のサイト様を拝見したり、フリーで配布されているスクリプトを見ると、書き込むファイルに対して、 $fp = fopen('bbs.log', 'r+'); flock($fp, LOCK_EX); … とやっていると思うのですが、perl記述のcgiで掲示板を作成したときは、書き込むファイルとは別にロック用のファイルを用意し、(perl記述です) open(LOCK,"+<$lockfile"); flock(LOCK,2); open(IN,"$logfile"); .... close(IN,"$logfile"); open(OUT,"$logfile"); .... close(OUT,">$logfile"); としていました。(書き込むファイルが2つあったのでこのような方法をとってました) そこでphpでも同じ方法は使えるのでしょうか? $fp = fopen('bbs.log', 'r+'); flock($fp, LOCK_EX); … の方法を使おうと思っていたのですが、最初にログファイルを読み込むとき、 file("bbs.log"); という風にしているので、flockに記述すべきファイルハンドルが見当たりません。仮に取得できたとしても、file();の仕様からして内部にcloseが入ってそうなので、flockできたとしてもcloseで無効になってしまわないかが心配です。なのでこの場合はやはり別にログファイルを用意しないとできないということでしょうか。

    • ベストアンサー
    • PHP

専門家に質問してみよう