• ベストアンサー

Perl このプログラムの解説をお願いします

Perl初心者です。 簡易なタイマーのプログラムです。 (1)$s=shift||60; この部分の shift と || はどういった意味合いを持っているのでしょうか。 (2)for(1..$s) このfor構文の括弧内はどういった意味合いを持っているのでしょうか。 $s=shift||60; $|=1; for(1..$s){ sleep 1; print"$_\r" } print"\n"

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

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

  • ベストアンサー
noname#208829
noname#208829
回答No.5

なぜ誰も質問に回答しないのでしょう? http://search.cpan.org/~rjbs/perl/pod/perlsyn.pod に "Many of Perl's syntactic elements are optional. Rather than requiring you to put parentheses around every function call and declare every variable, you can often leave such explicit elements off and Perl will figure out what you meant. This is known as Do What I Mean, abbreviated DWIM. It allows programmers to be lazy and to code in a style with which they are comfortable." とあるとおり、Perl は省略の多い言語なので読みづらいと思います。 ご質問のプログラムを省略せずに書くと次のようになります。 $seconds = shift(@ARGV) || 60; $| = 1; for $_ (1 .. $seconds) { sleep 1; print "$_\r"; } print "\n"; $s を $seconds に変えてみました。 @ARGV は argument vector の略称で、コマンド プロンプトから >perl timer.pl 180 のようにプログラムを実行した場合に、コマンドライン引数である「180」が格納される配列です。 shift は配列の先頭の要素を取り除いて返す関数ですが、配列を何も渡さないと @ARGV を shift します。 つまり shift() は shift(@ARGV) と同じです。かっこは省略可能なので単に shift と書いても同じです。 (ただしサブルーチンの中での shift は shift @_ を意味します。) したがって $s = shift || 60; というのはコマンドライン引数が渡されたらコマンドライン引数、渡されなかったら「60」を $s に代入するという意味になります。 この書き方はコマンドライン引数を受け取りつつ、デフォルト値も設定したいときによく使われます。 $| = 1; については説明は不要でしょう。 for (1 .. $s) { # ここに繰り返したい処理を書く } の 1 .. $s というのは「1 から $s までの整数のリスト」を意味します。 この .. というのは範囲演算子と呼ばれるもので、たとえば 1 .. 10 と書くと (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) というリストを簡単に作ることができます。 しかし、この場合は「1 から $s までのリストを作る」というよりかは、「要素数 $s のリスト」を作って、それを for 文でループすることにより、「$s 回ループさせる」ことを目的としています。 たとえば同じ処理を 10 回繰り返したいときは for (1 .. 10) { # ここに処理 } と書けばよいわけですが、それと同じで for (1 .. $s) { # ここに処理 } と書くことで同じ処理を $s 回繰り返すことができるわけです。 繰り返すごとに $_ に 1 から $s までの整数が順番に代入されていきます。 sleep 1; を $s 回繰り返せば $s 秒 sleep したことになりますから、もとのプログラムの意味が明らかになったかと思います。 また何かありましたら補足してください。

gohandaisuki520
質問者

お礼

なるほど~、とてもわかりやすい。。。 コマンドライン引数からshiftしているわけですね。 $hoge = shift;という形の使い方はほうぼうで見るのですが、意味がわからず困っていました。 ありがとうございます

その他の回答 (4)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.4

shift は ・(指定した) 配列の要素を 1つずつ (添え字の小さい方に) ずらす ・押し出された (元) 先頭要素を返す わけだから, 厳密にいうと「配列から値を取り出す」とはちょっと違う.

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.3

> ||演算子はorの用法であるというのは分かるのですが… or die みたいのはよく目にします。そういった感じでしょうか? そうです。違いは優先順位です。 この式に括弧を付けるなら $s = (shift || 60) ; です。 $s= shift or 60 ; だと ($s = shift) or 60 ;の意味になります 「左被演算子が真であれば、右被演算子は評価さえ 行なわれないということです」 にしたがって (1)まず shift を評価する。→ (デフォルトの)配列から先頭要素を取り出す。取り出した値が「評価結果」 (2) (1)が真ならば右側は評価しない。(1)が最終結果 (3) (1)が偽ならば右被演算子である 60 が評価→定数なので、そのままの60が評価結果 となります。 A or die も同様に (1) Aを評価.成功すると真/失敗すると偽になる (2) Aが真ならそこまで (3) Aが偽なら dieを評価→プログラム強制終了 となります。 and, &&も真偽が逆なだけで、同様な処理をします。 > shiftには、配列から値を取り出す以外の使い道があるんですか? shiftにはそれしかありません。

gohandaisuki520
質問者

お礼

回答ありがとうございます。

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.2

一応、日本語訳も。 http://perldoc.jp/docs/perl/5.14.1/perlop.pod shiftは関数なんでperlfuncですね http://perldoc.perl.org/functions/shift.html http://perldoc.jp/docs/perl/5.14.1/perlfunc.pod ちょっと難しいのは、|| の説明にある「左被演算子が真であれば、右被演算子は評価さえ 行なわれないということです」くらいです。 あとは読めばわかると思います。

gohandaisuki520
質問者

補足

回答ありがぞうございます。 ||演算子はorの用法であるというのは分かるのですが… or die みたいのはよく目にします。そういった感じでしょうか? shiftには、配列から値を取り出す以外の使い道があるんですか? $s=shift||60;

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

はい.

参考URL:
http://perldoc.perl.org/perlop.html
gohandaisuki520
質問者

お礼

英語は難しいです・・・><

関連するQ&A

  • このプログラムの解説をお願いできないでしょうか?

    以下の,意味を教えていただけると幸いです。 私は,HTMLからPerlに送り,再度記入者へ確認表示をさせたいと思っております。その中でこの部分が分かりません。お願いいたします。 for( $aIndex1 = 0 ; $aIndex1 < 20 ; $aIndex1++ ){ for( $aIndex0 = 0 ; $aIndex0 < 2 ; $aIndex0++ ){ $varName = "k" . $aIndex0 . $aIndex1 ; $anAns[ $aIndex0 ][ $aIndex1 ] = $input{ "$varName" }; $anAns[ $aIndex0 ][ $aIndex1 ] =~ s/\r\n//g ; } }

    • ベストアンサー
    • Perl
  • CからPerlへの変換がうまくいきません

    Cで作った二項分布の計算プログラムをPerlで書き直しています。 ユーザ関数の使い方がよくわかりません。 どこが間違っているか教えていただけませんでしょうか? 余談ですが、ソースが左揃えになるのを防ぎたいのですが…。 #!/usr/bin/perl $p = 0.5, $s = 0, $t = 0, $combination = 0, $binarydistribution = 0; printf("n="); $n = <STDIN>; for ($r = 0; $r <= $n; $r++){ $combination = &factorial($n) / (&factorial($r) * &factorial($n - $r)); $s = 1; for ($i = 1; $i <= $r; $i++){ $s = $s * $p; } $t = 1; for ($i = 1; $i <= $n - $r; $i++){ $t *= (1 - $p); } $binarydistribution = $combination * $s * $t; printf("%.15f\n", $binarydistribution); } sub factorial{ $j = @_; $x = 1; for ($i = 1; $i <= $j; $i++){ $x *= $i; } return $x; }

    • ベストアンサー
    • Perl
  • Perlで早いプログラムを作りたい

    perlの初心者です。 一つの配列の構成要素が100~1000のものが1000個ほどあります。 ある配列の一つの要素が他の配列に何個づつあるかを調べています。 作ったプログラムは次の三つですがとても遅く、もっと早い方法があれば 教えてください。 1.foreach $a(@hairetsu1){     $n=0;     foreach $b(@hairetsu2){       $n++ if $a =~ $b;     }   } 2. foreach $a(@hairetsu1){     $n=grep(/$a/,@hairetsu2);  } 3. for($i=0;$i<length(@hairetsu1);$i++){    $n=0;    for($j=0;$j<length(@hairetsu2);$j++)      $n++ if $hairetsu1($i) =~ $hairetsu2($j);    }  } 上が一番早く下に行くほど遅いですがあまり違いはありません。 よろしくお願いします。

  • Active Perlでsleepを使う。

    OS:Windows XP Home Edition インタプリタ:Active Perl(v5.8.8 built for MSWin32-x86-multi-thread) 簡単なスクリプトを作っていたのですが、 sleepについて質問があります。 #!/usr/bin/perl $a = 3; $b = 4; if($a > $b){ print "aが大きい"; } else{ print "bが大きい"; sleep(20); } このようなプログラムを書いたとき、 「bが大きい」が20秒遅れて表示されるのは 正しいですか? 私は「bが大きい」が表示されてから、20秒待つように 思えるのですが、実際の動きは「bが大きい」が20秒遅れて 表示されます。

    • ベストアンサー
    • Perl
  • perlの文法について

    はじめましてstaraman_sです。 今はPerl/CGI辞典という本を使いながらPerlの勉強をしていますが、インターネットで検索しても解決できず困っています。 皆さんのお力をお貸しください。 疑問点 sub getCookie { my ($tmp, $name, $value); for $tmp (split(/; */, $ENV{'HTTP_COOKIE'})) { ($name, $value) = split(/=/, $tmp); $value =~ s/\%([0-9a-fA-F][0-9a-fA-F])/pack("C", hex($1))/eg; $COOKIE{$name} = $value; } } 本の中の掲示板のプログラムの中に上記のようなプログラムが書いてあるのですが、最後の方に$COOKIE{$name} = $value;とあります。変数$COOKIEの後に中括弧を使い{$name}と書いているのは、どういった文法からきているのでしょうか。 よろしくお願いいたします。

    • ベストアンサー
    • CGI
  • 以下のperlのプログラムについて教えて下さい。

    次のプログラムは”多くのファイルの名前を一度に変更する”です。 (参考書から持ってきました) perlの初心者、というよりパソコンの初心者で参考書等で調べても わからないことが多く困っています。 #! /usr/bin/perl $op = shift or die"Usage: rename expr [files]\n"; chomp(@ARGV = <STDIN>) unless @ARGV; for (@ARGV) { $was = $_; eval $op; die $@ if $@; rename($was,$_) unless $was eq $_; } 質問 1. opは何ですか? 2. Usageは何ですか? 3. exprは何ですか? 4. ARGVは何ですか? 5. evalは何ですか? 6. wasは何ですか? 7. eqは何ですか? 8. このプログラムにおいてファイルは    どこのディレクトリでもリネーム出来るのでしょうか? 9. 出来ればプログラムの一行一行について説明をして下さい。 勉強不足で申し訳ありませんが、急ぎで知りたいので 宜しくお願い致します。

    • ベストアンサー
    • Perl
  • テキストエリアのインプットをPerlプログラムへ

    基本事項だと思うのですが質問させてください。 まず、HTMLファイル上に <form method= "post" action ="http://localhost/test.cgi> <textarea name ="story" cols="60" rows="10"> This is a test. </textarea> ... <input type="submit" name="submit_story" value="submit"> とプログラムを組みます。 その後、perlプログラムにテキストエリアの内容を送りユーザがsubmitボタンを押したときに HTMLファイルとして出力します。 そのPerlは以下のように組みました。 print "Content-type: text/html\n"; print "\n"; print "<html>\n"; print "<head>\n"; print "<title>The test of CGI</title>\n"; print "</head>\n"; print "<body>\n"; $story = $_POST["story"]; print "<p><h3>Textarea says $story </h3></p>\n"; print "</body>\n"; print "</html>\n";  しかし、$storyは表示されませんでした。 どこがおかしいのでしょうか? もしよければアドバイスをお願いします。

    • ベストアンサー
    • CGI
  • Win98+PWS4.0でPERLが動作しません

    Win98+PWS4.0でPERLを動作させたいのですがうまくいきません。 ディレクトリ「Inetpub」-「scripts」へTEST.PLという名で 下記のプログラムを入れて実施すると、 --------------- #!/user/local/bin/perl print "Content-type: text/html\n\n"; print "<html>\n"; print "<body>\n"; print "<p>\n"; print "Hello\n"; print "</p>\n"; print "</body>\n"; print "</html>\n"; --------------- HTTP エラー 403 403.1 許可されていません: 実行アクセスは許可されていません --------------- と出ます。 レジストリの設定は ".pl",".cgi”とも「C:\Perl\Bin\Perl.exe %s %s 」として、 PWSの設定で「scripts」は”実行””スクリプト”とも チェエク入をれています。 「wwwroot」のルートへ置いても同様のエラーが発生します。 DOS窓から「Inetpub」-「scripts」内でTEST.PLとすると 正常に表示はされます。 PerlへのパスもC:¥から実行確認済みです。 何が原因と考えられるでしょうか。 宜しくご教示お願いします。

  • perlによる外部プログラムの実行

    perlにてCGIを作成しています。 ブラウザでCGIにアクセスしたとき、gpgというコマンドプロンプトの プログラムを実行したいと考えており以下のようなプログラムを作成しました。 test.batを単体で実行したときにはうまく動作するのですが、CGIを介して 実行するとうまくいきません。 CGIのプログラム (WriteCmd.cgi) **********************************  #!c:/Perl/bin/perl  print "Content-type: text/html\n\n";  print "test.batの実行\n<br>";  system("test.bat");  exit; ********************************** test.bat **********************************  gpg --batch --gen-key sample.txt ********************************** またtest.batの内容を **********************************  mkdir test ********************************** としてみるとディレクトリがちゃんと作成できるので WebサーバやPerlのパスの問題ではないと考えております。 よい解決方法がありましたら教えていただけると助かります。 よろしくお願いします。

    • ベストアンサー
    • CGI
  • 以下のperlのプログラムについて

    以下は、多くのファイルの名前を一度に変更するための プログラムのはずなのですが・・・(参考書からもってきました) 分からないところがあるので教えて下さい。 #! /usr/bin/perl/ $op = shift or die"Usage: rename expr [files]\n"; chomp(@ARGV = <STDIN>) unless @ARGV; for(@ARGV){ $was = $_; eval $op; die $@ if $@; rename($was,$_) unless $was eq $_; } 1. opは何ですか? 2. Usageは何ですか? 3. exprは何ですか? 4. ARGVは何ですか? 5. wasは何ですか? 6. $_は何ですか? 7. eqは何ですか? 8. ファイルはどこのディレクトリに入っているものか  宣言しなくていいのですか? 9. できれば、プログラムの一行ずつ教えて頂けると助かります。 perlの初心者、というよりパソコンを使う事自体が 初心者でわからないことが多く困っています。 参考書でいろいろ調べましたが、まだ分からなくて・・・ 勉強不足で申し訳ありませんが宜しくお願い致します。

    • ベストアンサー
    • Perl

専門家に質問してみよう