• ベストアンサー

Perlスクリプト (); wantarry, (localtime)[0..2]; について。

人様の作ったスクリプトの解析をしています。 下記のスクリプトについて質問があります。 my $now = zikoku(); print "$now です。\n"; sub zikoku { my ($sec, $min, $hour) = (localtime)[0..2]; if (wantarray) { return ($hour, $min, $sec); } else { return sprintf "%02d:%02d:%02d", $hour, $min, $sec; } } まず、zikoku(); の部分なのですが、現在自分はサブルーチンは&で呼び出すものとしか認識しておらず、ここではどのような用法で使われているのかがわかりません。();は何なのでしょうか?? また、localtime関数の次の[0..2]の意味が分かりません。 そして、wantarray関数自体の働きは一応理解しているのですが、ここではwantarray関数にどのような意味があるのかが分かりません。 分かる方いらっしゃいましたらご教授頂けると幸いです。よろしくお願いします。

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

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

  • ベストアンサー
  • hara_peko
  • ベストアンサー率28% (11/38)
回答No.5

戻り値が配列の時・・・というよりは、戻り値として配列を期待されている時に wantarray が真になります。 たとえば No.4 の方が書かれている my @now = zikoku(); のように、配列に代入する時や、 print zikoku(); の様なケースです。これらはリストコンテキスト(文脈上リストとして解釈される)といいます。 逆に my $now = zikoku(); はスカラー変数に代入しようとしていますのでスカラーコンテキスト(文脈上スカラーとして解釈される)です。print の例で言うと、 print scalar zikoku(); のように scalar と言う関数を使えばスカラーコンテキストを強制することができます。 戻り値はサブルーチンの中で最後に評価された式の値です。もしくは今回の関数のように return で「これを返すんですよ」と明示してやります。 書物で言えば「初めてのPerl」を読めば用語その他すっきりするのではないでしょうか。(結構歯ごたえがありますが。(^^;)

fortunefeeling
質問者

お礼

なるほど、そういうことでしたか。参考になりました、ありがとうございました!

その他の回答 (4)

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.4

>zikoku(); の部分なのですが、現在自分はサブルーチンは&で呼び出すものとしか認識しておらず、ここではどのような用法で使われているのかがわかりません。();は何なのでしょうか?? サブルーチン呼出は、定義がされる前に呼び出す場合、&を付ける必要があります。(単なる文字定数として解釈されてしまうため) 引数無しでサブルーチンを呼び出す場合は、( )は、本来必要ありませんが、この場合、( )があることで、サブルーチン呼出として解釈されます。("()"が付いていることで定数文字列じゃなく関数呼出だとわかる) >localtime関数の次の[0..2]の意味が分かりません。 配列スライスと言います。 @array[0..2]とすれば ($array[0],$array[1],$array[2]) を表します。 my ($sec, $min, $hour) = (localtime)[0..2]; とすれば、localtimeが返すリストの最初の3つを取り出して左辺のそれぞれに代入することになります。 >ここではwantarray関数にどのような意味があるのかが分かりません。 つまりサブルーチンが配列を要求する場面で使われているか、スカラーを要求する場面で使われているかを判断して、配列の場合配列、スカラーを要求されている場合スカラーを返すために(場面判断のために)使います。 質問文のスクリプトの場合 my $now = zikoku(); は、文字列として要求されているので、サブルーチンは、"hh:mm:ss"を返すということになります。 仮に my @now = zikoku(); で呼び出されていたら (h, m, s) を返すということです。 なぜ、わざわざそういうようにするのかというと、この(文字列として要求される)場面だけでなく、他の場面でも使えるように、使い回しが利くように作っているのだと思います。

fortunefeeling
質問者

お礼

分かりやすい説明ありがとうございます!参考になりました。

  • hara_peko
  • ベストアンサー率28% (11/38)
回答No.3

アレ?私質問の意味を取り違えたでしょうか? if (ブール値) {  #ブール値が真の場合 } else {  #ブール値が偽の場合 } なので wantarray が真偽を返さないと if 構文が動作しない・・・のですが・・

fortunefeeling
質問者

お礼

すいません、自分まだまだ基礎知識が足りてないです・・。 wantarrayは、実行中のサブルーチンの戻り値として、リストが要求されている場合に真を返し、スカラーが要求されている場合には偽を返す、とウェブ上のリファレンスには載っているのですが(おそらく、話題のサブルーチンを例にして言えば、戻り値が配列の時は ($hour, $min, $sec) を返し、戻り値が変数の場合は sprintf "%02d:%02d:%02d", $hour, $min, $sec を実行して返すということなのだと解釈してますが合ってるでしょうか??)、そもそも「実行中のサブルーチンの戻り値」とは具体的に何を指しているんでしょうか??そこからして理解してなかったです。「戻り値」の定義自体もちょっとよく分かってないかもしれません。。そして、なぜ時刻をブラウザに表示させるのにwantarrayを使わなければいけないのかが分からないのです。 @yobi = ('日', '月', '火', '水', '木', '金', '土'); ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); $year += 1900; $mon += 1; print "$year年$mon月$mday日($youbi[$wday]) $hour時$min分$sec秒\n"; 上のスクリプトでも出来るのに。なぜわざわざwantarrayを使うのだろう・・・?と。 また なぜ (localtime)[0..2] なのだろう?と。[0..2] って何ですか?と聞くよりは (localtime)[0..2] って何ですか?と聞いたほうが早かったかもしれません。 よろしければご教授おねがいします。

  • hara_peko
  • ベストアンサー率28% (11/38)
回答No.2

「真を返す」ではなく、 「真の場合には(リストコンテキストの場合)」、($hour, $min, $sec) を返し、 「偽を返す」ではなく、 「偽の場合には(スカラーコンテキストの場合)」、23:33:35 の様な文字列を返すと言うことです。 ? は単体で使用されているのではなく、3項演算子 ブール値 ? 真の場合 : 偽の場合 として使用しています。参考URLの条件演算子の項をご覧下さい。

参考URL:
http://www.rfs.jp/sb/perl/02/03.html#4.%E8%AB%96%E7%90%86%E6%BC%94%E7%AE%97%E5%AD%90
  • hara_peko
  • ベストアンサー率28% (11/38)
回答No.1

zikoku(); 引数無しでサブルーチン zikoku を呼び出しています。 [0..2] 配列 スライス で検索してみて下さい。0..2 の部分は 0, 1, 2 と同じです。 前回質問されていた時には3項演算子で wantarray ? 真の場合 : 偽の場合 となってましたが、それが if の構文に変わっただけです。

参考URL:
http://www.rfs.jp/sb/perl/index.html
fortunefeeling
質問者

お礼

回答ありがとうございます! 3つ目のwantarrayですが、すいません、質問の仕方が悪かったです。ここでwantarrayを使って、リストが要求されている場合に真を返し、スカラーが要求されている場合には偽を返すことにどのような意味があるのか分からないという意味だったんです。 また、一つ質問を追加させてください。一つ前の質問のことなのですが、wantarray ? の「?」は一体どのような意味を持っているのでしょう??ご教授よろしくお願いしますm()m

関連するQ&A

  • localtimeについて

    まだCGIを勉強はじめのなのですが、localtimeについて質問させてください。 書籍で時間取得には ($sec,$min,$hour,$mday,$mon,$year,$wno) = localtime(time); とし、time関数で得たものをlocaltime関数で整形 といった事が書かれています。 まずわからないのが最初の ($sec,$min,$hour,$mday,$mon,$year,$wno) = の部分なのですが、カッコ内に変数を並べるというのはどういった命令なのでしょうか?書籍ではここまででこのような使い方や記述は出てきていないので、それ自体がよく理解できずにいます。それとも($sec,$min,$hour,$mday,$mon,$year,$wno) = localtime(time);をおきまりパターンとしてワンセットで覚えるべき事なのでしょうか。 続いてlocaltime(time)ですが、これは()内のtime関数によって取得された1970年基準からの秒数を、localtimeによって英語圏での標準的な日付時間表記に直して表示するという事で良いのですよね? これが、なぜ ($sec,$min,$hour,$mday,$mon,$year,$wno) とすることで各変数に割り振ることができるのかがよく分かりません。 これらはおきまりパターンとして覚えるべき事なのでしょうか?それとも配列のようにあるパターンに乗っ取って書かれ得いる事で他に応用がきくような意味合いのものなのでしょうか? ご教授いただきたく思います。 よろしくお願いします。

    • 締切済み
    • CGI
  • Perl 水曜日に処理を変えたい

    人の作ったものですが、月曜午前0時で処理を切り替えるようになっています。 これを水曜午前0時に変更するにはどうすればいいでしょうか? 長いですがよろしくお願いします。 sub GetNextWDayTime { my $time = time; my ($sec, $min, $hour, $wday) = (localtime($time))[0,1,2,6]; my $now = ($wday * 60 * 60 * 24) + ($hour * 60 * 60) + ($min * 60) + $sec; my $next = ($_[0] * 60 * 60 * 24) + ($_[1] * 60 * 60) + ($_[2] * 60) + $_[3]; #if $next is small, $next is next week. if($next < $now){ $time = $time + (60 * 60 * 24 * 7); } $time = $time + (($_[0] - $wday) * 60 * 60 * 24); $time = $time + ($_[3] - $sec); $time = $time + (($_[2] - $min) * 60); $time = $time + (($_[1] - $hour) * 60 * 60); return $time; } sub GetLastWDayTime { my $time = time; my ($sec, $min, $hour, $wday) = (localtime($time))[0,1,2,6]; my $now = ($wday * 60 * 60 * 24) + ($hour * 60 * 60) + ($min * 60) + $sec; my $last = ($_[0] * 60 * 60 * 24) + ($_[1] * 60 * 60) + ($_[2] * 60) + $_[3]; #if $last is large, $last is next week. if($last > $now){ $time = $time - (60 * 60 * 24 * 7); } $time = $time + (($_[0] - $wday) * 60 * 60 * 24); $time = $time + ($_[3] - $sec); $time = $time + (($_[2] - $min) * 60); $time = $time + (($_[1] - $hour) * 60 * 60); return $time; }

    • ベストアンサー
    • Perl
  • localtime()での時間差の計算の仕方

    $ENV{'TZ'} = "JST-9"; my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); my $now =sprintf("%04d/%02d/%02d-%02d:%02d",$year+1900,$mon+1,$mday,$hour,$min); とすると 2007/01/28-15:56 のようにデータとして取得できるのですが・・・ これと登録日($date=2006/12/31-12:25)との日数差の計算ができません $now-$date とすると年数のところしか計算できず1としか表示できません 登録7日後以降にイベントを発生させたいのですが計算ができないのでうまくいきません 両方time()でやれば$now-$date>604800 とすればなんとかできるのですが登録日は『2006/12/31-12:25』の形で使いたいのです 登録日と現在の日数の差の計算方法を教えてくださいm(--)m

    • ベストアンサー
    • CGI
  • Perlでの Timeの足し算

    時間の足し算をやりたい。訳あってライブラリが使えません。 方法は無いでしょうか? 仮にライブラリが使えるなら、下記のようでうまく行っています。 --------------------------------------------------- use Time::Local; $year=2008; $mon =10; $mday=24; $hours = 23; $min = 0; $sec = 0; $time = timelocal($sec, $min, $hours, $mday, $mon - 1, $year); $a1=($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime($time ); $mytimeORG= sprintf("%04d/%02d/%02d %2d:%2d", $year + 1900, $mon +1, $mday,$hour,$min); print "$mytimeORG\n"; ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime($time + 32400); #9H加算 $mytime9H= sprintf("%04d/%02d/%02d %02d:%02d", $year + 1900, $mon +1, $mday,$hour,$min); print "$mytime9H\n"; ---------------------------------------------

    • ベストアンサー
    • Perl
  • CGIについて(時間表示)

    CGI初心者ですが、掲示板を作成中です。投稿するたびにメッセージの投稿時間がすべて現在時刻に書き換わります。 メッセージ毎に時間表示させたいのですが、いかのプログラムのどこを変更すればよいのでしょうか?宜しくお願いいたします。 # 時間処理 sub totime { ($sec,$min,$hour,$mday,$month,$year,$wday,$yday,$isdst) = localtime(time); $year +=1900; $month++; $year = sprintf("%04d", $year); $month = sprintf("%02d", $month); $mday = sprintf("%02d", $mday); $hour = sprintf("%02d", $hour); $min = sprintf("%02d", $min); $sec = sprintf("%02d", $sec); $date = "$month/$mday $hour:$sec"; }

    • ベストアンサー
    • CGI
  • 掲示板への書き込み時間

    掲示板CGIについて質問です。 使おうとしているスクリプトはそのままアップロードすると書き込みした時間の表示が 「4/14 (Sun) 17:10」 のようになります。 これを 「2003 4/14 (日) 17:10:50」 のように年と秒まで加えたいのです。 それで後者のように表示される掲示板CGIを参考にしてみましたが、目立った違いはないように思え、どこをどう変更すれば年や秒まで表示されるようになるかわかりません。 思い当たる部分はこのあたりなのですが…。 ↓このように記述されています ************ $ENV{'TZ'} = "JST-9"; ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); $year = sprintf("%02d",$year + 1900); $month = sprintf("%02d",$mon + 1); $mday = sprintf("%02d",$mday); if ( substr($month,0,1) == 0 ) { $month =~ s/0/ /; } if ( substr($mday,0,1) == 0 ) { $mday =~ s/0/ /; } $hour = sprintf("%02d",$hour); $min = sprintf("%02d",$min); $sec = sprintf("%02d",$sec); $youbi = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat') [$wday]; $date_now = "$month/$mday ($youbi) $hour:$min"; ************ CGIに手を加えてレイアウトの変更くらいはいつもやっています。 もし書き換える方法がありましたら教えていただければと思います。 どうぞよろしくお願い致します。

    • ベストアンサー
    • CGI
  • Perlの日付取得で月の表示がおかしい

    下記は、メールフォームCGIに書き込まれた日時などの情報をlog.cgiというファイルに書き出すスクリプトです。 2012/01/04 21:05:45 のような感じで、日付が刻まれるのですが、このうち月の部分がどの月に処理を行ってもいつも01になってしまうのですが、当方直し方がわかりません。 下記が実際の記載箇所です。4行目がおかしいのだと思いますが、どなたかお分かりの方、教えていただけないでしょうか。 my $path = "log.cgi"; my $ip = $ENV{'REMOTE_ADDR'}; ($sec, $min, $hour, $mday, $month, $year, $wday, $stime) = localtime(time()); my $time = sprintf("%04d\/%02d\/%02d %02d\:%02d:%02d", $year + 1900, $mon + 1, $mday, $hour, $min, $sec); my $message = $in{'メッセージ'}; $message =~ s/\r\n/ /g; $message =~ s/\n/ /g; if (open(FOUT, ">> $path")) { print FOUT "$time\t$ip\t" . $in{'お名前'} . "\t" . $in{'E-mail'} . "\t" . $message . "\r\n"; close(FOUT); } よろしくおねがいいたします。

    • ベストアンサー
    • Perl
  • 先月(YYYYMM)の生成方法

    言語は問いません。 先月をYYYYMM形式の文字列で得るクールな方法ってありますか? Perlで以下のように書けば正しく動きますが、なんかダサイ気がします。 my ($sec, $min, $hour, $mday, $mon, $year) = localtime ; $year -= 1 if $mon == 0; $mon = '12' if $mon == 0; $yearmonth = sprintf("%4d%02d", $year+1900, $mon); よろしくお願いします。

  • Perlで日付を取得する

    Perlで日付を取得する perlで1週間分の日付を取得し、セレクトボックスに格納したいと思っています。 なるべくいま使っているサブルーチンを使いたいです。 # 現在日時を文字列化する sub get_date_string { # local(@week) = ("日", "月", "火", "水", "木", "金", "土"); local(@week) = ("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"); local($sec, $min, $hour, $day, $mon, $year, $weekday) = localtime(time); $year += 1900; $mon++; # 文字列化する if ($hour < 10) { $hour = "0$hour"; } if ($min < 10) { $min = "0$min"; } if ($sec < 10) { $sec = "0$sec"; } $weekstr = $week[$weekday]; return "$year-$mon-$day ($weekstr) $hour:$min"; # return "$year年$mon月$day日 ($weekstr) $hour時$min分$sec秒"; } これを別のルーチンで、 $today = substr(&get_date_string,0,10); $kinou = $today - 1; $ototoi = $today - 2; として、今日の日付だけでなく、昨日、おととい、その前の日を取得したいと試みましたが、今日は取得できても、$kinouや$ototoiは、すごい数字になってしまいます。 変わりに -24*3600と引いてみましたがダメでした。 文字列に変更されていないから引けないのでしょうか? かんたんに処理できそうでできないので、詳しいやり方を教えてください。

    • ベストアンサー
    • Perl
  • perl-cgiのリネームについて

    Perl-CGIで ABCという、ディレクトリの中のファイルの名前を、ランダムな名前に変換したいのですがうまくいきません。 これを動作させるたびになぜか、どんどんファイルが減っていってしまいます。 どなたか、教えていただけないでしょうか? 宜しくお願い致します。 #!/usr/local/bin/perl print "Content-Type: text/plain\n\n"; $| = 1; my ($sec,$min,$hour,$mday,$mon,$year,$wno) = localtime(time); my ($nowtime) = sprintf("%02d_%02d_%02d_%02d_%02d_",$year+1900,$mon+1,$mday,$hour,$min,$sec); #ディレクトリのファイル個数を記録する $dir = "./ABC/"; # ← ディレクトリを変数にセットする opendir DIR, $dir; @files = grep { !m/^(\.|\.\.)$/g } readdir DIR; # ← 「.」 「..」 以外のファイルを取得 close DIR; srand; for (my $i = @files; --$i; ) { my $j = int rand ($i + 1); next if $i == $j; @files[$i, $j] = @files[$j, $i]; } $num = 0; use File::Copy; foreach(@files){ $getpath = "$dir"."$_"; if( copy($getpath, "$dir".$nowtime.$num++.'.dat') eq 1){ $num++; unlink($getpath);}else{print "Copy Error"; exit;} }

    • ベストアンサー
    • CGI