printが使えない?初心者が困っています

このQ&Aのポイント
  • 初心者がTemplate-Toolkitを使った関係でprintが使えなくなる可能性はあるのか?質問しています。
  • Perlのプログラムで、サブルーチン内でprintを使用したいと思っていますが、うまくいきません。
  • クラスの考え方を理解し始めた初心者が、printの使い方についてアドバイスを求めています。
回答を見る
  • ベストアンサー

printが使えなくて困ってます(初心者)

初心者です。的外れなことを書いていたらすいません。 Template-Toolkitを使った関係でprintが使えなくなるということはありえますでしょうか? ソースすべてはお見せできないので、大まかに書きます。 #! /usr/bin/perl my $luck = new Luck::Mini $luck->execute; package Luck::Mini use Template; sub new {  my $class = shift;  # 省略 } sub excute {  #  eval { subroutin_1() };  # } sub template {  # Templateを使ったサブルーチン } sub subroutin_1 {  #  $rslt = sunroutin_2( );  #  # template に渡す$paramsを生成(パラメータ)  template( abc.html, $params ) # テンプレートを生成して終了 } sub subroutin_2 {  #  for ( my $n = 0; $n < 2; $n ++ ) {   #  }  my $result = [];  # $result にデータを代入する作業  #  return $result; } subroutin_2内で行われいるループの回数$n をprintしたり、 $result をprintしたりしたいと思っています。 現在やっとクラスの考え方が分かり始めたレベルですので、お手柔らかにお願いします。

  • brosis
  • お礼率94% (100/106)
  • Perl
  • 回答数10
  • ありがとう数13

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

  • ベストアンサー
  • TYWalker
  • ベストアンサー率42% (281/661)
回答No.10

・なんでそこで eval するんでしょうか。 ・print で表示するっていうのは、CGI 機構を使って Web ブラウザーに対してですよね? HTTP ヘッダーを出さないと CGI は出力されないので、1回目と2回目で結果が変わることもあると思います。 ・普通はこういうとき warn を使ってエラーログを確認します。warn を使っても結果は一緒ですか? >知識がなく、まともな質問ができないのが悔しいです。 確かにおっしゃるとおりですね。であれば勉強すればいいと思います。 自分に関してもいえますが、Web の掲示板を使って質問を投げるのはカンタンにできますから飛びつきがちなんですが、自分の質問を要領よく要約してツボをついた質問をするわけですから結構な技術力がいります。 「謎のプログラムが裏で動いているかも」とかいいながら、会社の業務のプログラムを適当にいじっておかしいとか言ってるの怖くないですか。ぼくだったら怖いです。土曜も、日曜も出勤ですよね。brosis さんの体も心配です。 遠回りですが、本なりなんなりで基本を勉強してから、ご自分の力で問題を解決するか、技術力があって brosis さんを指導することで報酬が得られる方のご指導を仰ぐのがスジだと思います。 少なくともぼくはもう自分の限られた能力の限界を感じますから、これにて手を引かせていただきます。お役に立てず申し訳ありませんでした。

brosis
質問者

お礼

eval "print $n"; したのは特に意図はありませんでした。 ずっと残しておいたコードが、たまたま今日初めてのCGIアクセスで効いた、それだけです。 >・print で表示するっていうのは、CGI 機構を使って Web ブラウザーに対してですよね? はい、そうです。 2回目のアクセス以降は、一切 print $n; も eval "print $n"; も subroutin_2 の中で効かなくなりました。 >「謎のプログラムが裏で動いているかも」とかいいながら、会社の業務のプログラムを適当にいじっておかしいとか言ってるの怖くないですか。 怖いとか、あまり深く考えていませんでした。ソースのバックアップとっているから大丈夫。。だろうと。 >遠回りですが、本なりなんなりで基本を勉強してから、ご自分の力で問題を解決するか、技術力があって brosis さんを指導することで報酬が得られる方のご指導を仰ぐのがスジだと思います。 そうですね。上長に相談します。 こんなにシツコク、分かりにくい質問で申し訳ございませんでした。 長い間お付き合い頂きまして、ありがとうございました。

その他の回答 (9)

  • TYWalker
  • ベストアンサー率42% (281/661)
回答No.9

ひとつ前の回答で上げた豆プログラムの $m と同じ状態ですね。 グローバル変数をサブルーチンの中で変えたのに、サブルーチンの実行後値がリセットされることはありえません。 my $n; print $n; # 何も表示されない($n は undef だから。警告が起こる) &foo(); print $n; # 3 と表示される sub foo { $n = 3; }

brosis
質問者

お礼

ありがとうございます。 本日、初めてのサーバーへのアクセスにおいて、 my $n; sub subroutin_2 {  #  for ( $n = 0; $n < 2; $n ++ ) {  #  eval "print $n"; } の、eval "print $n"; が表示されました。しかし、すぐさま2回目のアクセスで、eval "print $n"; は表示されなくなりました。 この不思議(?)なサーバーの動きは、何か裏で他のプログラムでも動いているかの様です。 知識がなく、まともな質問ができないのが悔しいです。

  • TYWalker
  • ベストアンサー率42% (281/661)
回答No.8

さっきな subroutin_2 の中の for でも $n が my 宣言されてましたけど、どっちが正しいんですか? my $n; subroutine_2 { for (my $n... この2つの $n が赤の他人であることは分かりますよね? $n にスコープ(有効範囲)があるから。 #! /bin/perl my $n = 'global'; my $m = 'global2'; warn "1: $n"; warn "2: $m"; &foo(); warn "6: $n"; warn "7: $m"; sub foo { my $n = 'sub'; warn "3: $n"; warn "4: $m"; for my $n (1..3) { warn "5: $n"; } warn "6: $n"; } を実行すると、 C:\Documents and Settings\you\デスクトップ\foo>foo.pl 1: global at C:\Documents and Settings\you\デスクトップ\foo\foo.pl line 6. 2: global2 at C:\Documents and Settings\you\デスクトップ\foo\foo.pl line 7. 3: sub at C:\Documents and Settings\you\デスクトップ\foo\foo.pl line 16. 4: global2 at C:\Documents and Settings\you\デスクトップ\foo\foo.pl line 17. 5: 1 at C:\Documents and Settings\you\デスクトップ\foo\foo.pl line 19. 5: 2 at C:\Documents and Settings\you\デスクトップ\foo\foo.pl line 19. 5: 3 at C:\Documents and Settings\you\デスクトップ\foo\foo.pl line 19. 6: sub at C:\Documents and Settings\you\デスクトップ\foo\foo.pl line 21. 6: global at C:\Documents and Settings\you\デスクトップ\foo\foo.pl line 11. 7: global2 at C:\Documents and Settings\you\デスクトップ\foo\foo.pl line 12. となります、と書けば回答になるでしょうか。

brosis
質問者

お礼

>この2つの $n が赤の他人であることは分かりますよね? 分かります。 sub subroutin_2 { の中で、print が効かないということで、  my $n;  for ( $n=0; $n < 2; $n ++ ) { をあきらめ、変更して、 my $n; sub subroutin_2 { と、することにしました。すみません説明が抜けていました。 今、引っかかっているのは、$n が subroutin_2 のスコープを抜けると値がリセットされるのでは?ないかと思っています。 「そんなことは有り得ない。」ならはっきりと否定して頂けたら有難いです。

  • TYWalker
  • ベストアンサー率42% (281/661)
回答No.7

ああ、GET メソッドでパラメーターを受けているということは、CGI をブラウザーから起動しているんですね。 状況がわかりました。 Template-toolkit というものは HTML を組み立てるものらしいですね。 その時点で気づくべきでしたね。 まとめると、 (1) CGI で Perl のスクリプトを起動している (2) HTML は Template-toolkit を使って組み立てている (3) データに不整合があるので、デバッグしている (4) プログラムの途中に print を挟んで中間データを確認したい (5) しかし、print の結果が((2) で Template-toolkit を使って組み立てた HTML を表示している、そのブラウザー画面に)表示されない (6) しかしながら、Template-toolkit の使用をやめると、print が起動する (7) そこで、Template-toolkit が干渉して print を使用不可にしているという怪奇現象があるようなので、OKWave に相談した という状況ですね。 Template-toolkit は HTML のテンプレート(枠組み)を生成し、その中に変動するデータを差し込んで美しく整形して出力してくれるものですね。 よって、Template-toolkit を使って HTML を表示する前に何か print で出力しても、Template-toolkit が HTML を表示するときに表示をクリアーしてしまうので、消えてしまうんですね。 ところが、Template-toolkit の使用を切れば、表示がクリアーされないので、print 出力が生きるということですね。 ということで、brosis さんのおっしゃる Template-toolkit が干渉して print の出力が消えてしまうと言うのは、ある意味当たっているんですね。 また、前のお礼にあった、 print qq#Expires: Mon, 26 Jul 1997 05:00:00 GMT\n#; print qq#Cache-Control: no-store, no-cache, must-revalidate\n#; print qq#Cache-Control: post-check=0, pre-check=0\n#; print qq#Pragma: no-cache\n#; print qq#Content-Type: text/html; charset=UTF-8\n#; printf qq#Content-Length: %d\n\n#, length $buffer; というのは HTTP ヘッダーですね。 これを出力するときに、それまでの print がクリアされているんですね。 よって、brosis さんのおっしゃるこれらの print が、デバッグ用の print をクリアーしてしまったというのもある意味当たっているんですね。 どうも、いい加減に見ていてすみませんでした。 で、以上の状況を踏まえて、プログラム中にデバッグのために中間データを出力するにはどうすればいいか。 以下のような手段が考えられます。 1. print の代わりに warn を使う。 データは HTTP サーバー(Apache か何かが動いていると思います。要は Web サーバーのこと)のエラー ログ(UNIX だとすれば、/var/log/error.log かなにか、Apache の設定によって異なる)を見ればよい。 そのまま表示するには % tail /var/log/error.log を使う。(tail コマンドは長大なテキストファイルの末尾のみを表示する) あるいは、warn で warn "brosis-debug: n", $n; のように常に brosis-debug: などとヘッダーをつけておけば、 % grep "brosis-debug:" /var/log/error.log とすれば brosis-debug: というヘッダーのついたログのみが表示されます。 2. HTML-toolkit でテンプレートを定義しているところに手を入れ、デバッグのために表示をしたい中間データ($n とか $result とか)を表示するエリアを作り、他のデータ同様そこに値を差し込む 3. 標準出力(ブラウザー画面)ではなく、何らかのデータ ファイルに print させる。 ただし CGI スクリプトは nobody というユーザーによって実行されるので、そいつに書き込み可能なディレクトリを作って書き込む必要があるから注意 4. sendmail コマンドを使って中間データを自分にメールさせる これ以前やったことがあります。 以上です。答になっていればいいがと思います。 なんかかえって時間をとらせてしまってすみませんでした。

brosis
質問者

お礼

ご回答ありがとうございます。 >どうも、いい加減に見ていてすみませんでした。 とんでもないです。 現在は、Template-toolkitのスクリプトをすっ飛ばしていますので、 printが使える状況です。 ただ引っかかるのが、サブルーチンの中でprint や warn が効かないことです。 例えば、 my $n; sub subroutin_2 {  #  for ( $n = 0; $n < 2; $n ++ ) {   #  }  print $n, "<br />";  print "AAA";  my $result = [];  # $result にデータを代入する作業  #  return $result; } print "BBB"; print $n; の print $n, "<br />"; や print "AAA"; が表示されないのです。 print "BBB"; は表示されます。 しかし、サブルーチン外の print $n; は表示されません。 サブルーチン内で print するのは、とりあえず置いといて、 サブルーチン外での print $n; の不表示は、 全く my $n; から値が代入されてないということになりすね。 しかし、 sub subroutin_2 は働いてはいるのです。 今、sub subroutin_3 { というものがあり、 my $prames; sub subroutin_3 {  #  my $ret = subroutin_2;  #  $params = {       result => $ret,       #       #  };  return $params; } print Data::Dumper-Dump( [$params] ); で、不整合な結果のデータですけど表示はされるのですから。 となると、print $n; で値が入ってないということは、 subroutin_2 内から外へのスコープの間に、$n の値をリセットしてしまう原因があるということですね。 こうなるとクラスとかオブジェクトの作り方の問題になるのでしょうか?

  • TYWalker
  • ベストアンサー率42% (281/661)
回答No.6

また連投ですみません。 print してみているのはデバッグのため(プログラムの動きを調べるため)ですよね? であれば print の変わりに warn を試すのも手だと思います。

  • TYWalker
  • ベストアンサー率42% (281/661)
回答No.5

なるほど、他の人が書いたプログラムの修正を負かされているんですね。 事情がわかりました。 失礼しました。 しかしながら、アドバイスは変わりません。 (1) use strict; use warnings; をつけてください。 (2) 最小の(動作する)プログラムを組んで、1個1個の機能を実験してください。 少なくともbrosisさんが抜き出した部分だけでは不具合の原因はわかりません。 あと、brosisさんが推測した原因(use Template; がメインルーチンやサブルーチンの print に干渉する)もありそうではないと思います。 あと、eval を介してのサブルーチン呼び出しが前からなら、前のプログラムの書き方もちょっとナゾです。 納期が決められていて、OKWave 以外に(もともとプログラムを書いた人や、会社の先輩などに)アドバイスが求められないなら、その体制もちょっと疑問です。 いやいや、無理な仕事を任されて困ることは誰でもあるものです。 苦しみを乗り越えたら強くなります。 がんばってください。

brosis
質問者

お礼

TYWalkerさん、アドバイスと激励ありがとうございます。  eval { subroutin_1() }; について説明していませんでした。 このコードは実際には、  my $action = sprintf '%s', $this->{page};  eval { $this->$action() }; です。 前のページから送られるGETクエリによって使うサブルーチンが変わります。(表示されるものが変わります。今回の件は、subroutin_1から使い始めます。) use strict; use warnings; についても大丈夫です。元々記述されておりました。すみません。

  • TYWalker
  • ベストアンサー率42% (281/661)
回答No.4

連投ですみません。 pm ファイルでなく、ファイルの中にメインとクラスが両方あるんですね、失礼しました。 で、メインで呼び出してるのは execute で、呼び出されてるのは excute ですけど(つづり間違いがありますけど)大丈夫ですか? で、excute の中で subroutin_1 を eval してるわけですけど、これ単純に呼び出さないで eval している理由はなぜですか?(eval でも動くようですけど・・・) subroutin_1 の中で sunroutin_2 を呼び出してますけど(つづり間違いがありますけど)大丈夫ですか? 昨日も言いましたが、 use strict; use warnings; を書いて、すべてのエラーと警告をつぶしてみましたか? brosis さんはたしかにかなりの初心者のようなので、長い難しいプログラムを書いてその一部分だけを書いて質問するというのはチョット無理だと思います。 もっとプログラムをギリギリ短くして、おかしいと思う現象が起こる最短のプログラムを作って、そのプログラムの全文と、警告、エラーを出してくれたら相談にのれると思います。 (一般にたとえ上級者であっても、質問に使うプログラムはギリギリ最小に書くものです)

brosis
質問者

お礼

ご回答ありがとうございます。 スペルミスは、OKwaveでのみです。すみません。 実は、エラーが出でいるわけではないのです。 こんな初心者に対して、長いソースコードによるデータ取得の不具合の修正が任されているのです。

  • TYWalker
  • ベストアンサー率42% (281/661)
回答No.3

#1 を書いたものです。 Template モジュールなるものでやっているのは、単なるまた別の print なので、それがユーザーサブルーチンの print に 影響を与えることはないと思います。 print "string"; というのは、実際にはそのときのデフォルトのファイルハンドルへの出力で、デフォルトのファイルハンドルは select FILEHANDLE; などのように別のファイルハンドルに設定されるまでは STDOUT というものになっています。もし別のファイルハンドルにデフォルトが変わっていたとしても print STDOUT "string"; のように明示的にファイルハンドルを書いてやればちゃんと標準出力に表示されるはずですのでためしてみてください。 あと、もし use Template; が疑わしいのなら、上のサブルーチンは特にそれに関係ないようなので一時的にそれを外してみればいいんじゃないでしょうか。 あと、本当に subroutin_2 は呼ばれてるんでしょうか。 上のコードは pm ファイルで、それを use するメインは別にあるんですよね? ・Template-Toolkit を使う ・pm ファイルを使う ・サブルーチンの仲で print を行う という問題がごっちゃになっていて、どこに問題があるのかわからなくなっていますね? であれば、急に難しいことをせずに、1個1個解決していくほうがいいと思いますよ。

回答No.2

for ( my $n = 0; $n < 2; $n ++ ) { でどうですか。 $n の スコープが for ループの外になってるのではと思います。 use strict; すると、その辺は指摘してもらえるかと。

brosis
質問者

お礼

ご回答ありがとうございます。 あえて my $n; for ( $n = 0; $n < 2; $n ++ ) { こうしてます。 for文の外で、print $n; をしてちゃんと2回ループされているか確かめるためです。

  • TYWalker
  • ベストアンサー率42% (281/661)
回答No.1

どこに print 書きました? my で作った変数はスコープが切れるとなくなりますよ。 具体的に言うと、  for ( my $n = 0; $n < 2; $n ++ ) {   #  } の $n は for ループの外に出ると消えちゃうし、 sub subroutin_2 {  #  for ( my $n = 0; $n < 2; $n ++ ) {   #  }  my $result = [];  # $result にデータを代入する作業  #  return $result; } の $result は subroutin_2 が終わると消えちゃいますよ。 プログラムは最初に(#! /usr/bin/perl のすぐ下に) use strict; use warnings; とかくと、いろいろ変なところがあると怒られるので便利です。

brosis
質問者

お礼

回答ありがとうございます。 for ( my $n = 0; $n < 2; $n ++ ) { を my $n; for ( $n = 0; $n < 2; $n ++ ) { にして subroutin_2内で print $n; しても表示されませんでした。 おそらくTemplateモジュールを使っているところで、 print qq#Expires: Mon, 26 Jul 1997 05:00:00 GMT\n#; print qq#Cache-Control: no-store, no-cache, must-revalidate\n#; print qq#Cache-Control: post-check=0, pre-check=0\n#; print qq#Pragma: no-cache\n#; print qq#Content-Type: text/html; charset=UTF-8\n#; printf qq#Content-Length: %d\n\n#, length $buffer; print $buffer; などとやっている関係でしょうか? この際、use Template; をやめちゃてます。 デバッグの作業を行う為です。 今は、 my $result; sub subroutin_2 {  #  # } みたいことをやってます。 本来は subroutin_2 内でprint Data::Dumper->( [$result] ); とか print $n; やりたいのですが。。 できますよねぇ?subroutin_2 内で。

関連するQ&A

  • HTML::Templateの初歩的な質問

    HTML::Templateを使用してサイトを構築しようとしてるのですが、うまくいきません。 例1のようにしたいのですが、どこが間違っているかを指摘していただきたく書き込ませて頂きました。 ちなみに例2ではうまく作動しています。 よろしくお願い致します。 サンプルコード ★sample.html★ <TMPL_LOOP name=arr> <p><TMPL_VAR name=val></p> </TMPL_LOOP> ★例1★ my $template = HTML::Template->new(filename => 'sample.html'); @arr = [ {val=>'1'},{val=>'2'},{val=>'3'} ]; $template->param(arr => \@arr); print "Content-Type: text/html\n\n"; print $template->output; ★例2★ my $template = HTML::Template->new(filename => 'sample.html'); $template->param(arr => [ {val=>'1'},{val=>'2'},{val=>'3'} ] ); print "Content-Type: text/html\n\n"; print $template->output;

    • ベストアンサー
    • Perl
  • Webサービスの参照渡し

    PHP初心者です。調べても有効な情報が得られなかったので質問します。 PHP(5.2.6)から(VB.NET2008で作成した)Webサービスを呼び出したのですが、 引数が値渡しになっているらしく、Webサービスで設定した値が返ってきません。 参照渡しにするにはどうしたらいいのでしょうか? -------------------------------------------------------------- ***[PHP]********************************** <?php $client = new SoapClient("http://IPAdress//WebSv.asmx?WSDL"); $AAA = "AAA"; $params = array('rAAA'=>$AAA); $result = $client->__soapCall("ATOB", array('parameters' => $params)); print_r($AAA); ?> ****************************************** ***[Webサービス]************************** <WebMethod()> _ Public Sub ATOB(ByRef rAAA As String) rAAA = "BBB" End Sub ****************************************** -------------------------------------------------------------- PHPを実行すると BBB と表示させたいが AAA と出てくる。 ちなみに呼び出し自体はうまくいっていて、エラーにもなっていません。

    • ベストアンサー
    • PHP
  • Perl 強制終了の回避について

    Attempt to free unreferenced scalar とは? http://oshiete1.goo.ne.jp/qa4237453.html の続きです。 とりあえず、下に現状で分かる最小限の再現性があるスクリプトを 書いておきます。 print &opentmpl("body"); print &opentmpl('footer'); # これがない場合はエラーにならない sub opentmpl { my $fn = shift; my $VAR = shift || {}; my $file = &{$fn}(); &regex(\$file, $VAR, '__([A-Z_\d]+?(\[\d+?\])?)__', ['$VAR->{"%s"}', '$1']); &regex(\$file, $VAR, '&{(.+?)}&', ['%s', '$1']); return $file; return undef; } sub regex { my $str = shift; my $VAR = shift; my $pattern = shift; my $replace = shift; $$str =~ s/((([^\n]*?)$pattern(?=.*))+(\n?))/&func($1, $VAR, $pattern, @$replace)/egs; return; } sub func { my $str = shift; my $VAR = shift; my $pattern = shift; my $buf = shift; $str =~ s/$pattern/$@ = ''; $_ = eval(sprintf($buf, map { eval($_); } @_)); $@ ? $@ : $_/egs; if($str =~ /^\s*\n?$/s) { return; } return $str; } sub body { print "Content-type: text/plain; charset=shift_jis\n\n"; return <<'HTML'; &{ return &opentmpl('table', {'TEST' => 'test'}); }& HTML } sub table { return <<'HTML'; __TEST__ HTML } sub footer { return <<'HTML'; test HTML } 調べてみた限りではActivePerl for Win32以外のPerlでも同様のよう です。 (Linux上でも同様のようです) 5.8.8ではエラーになりますが、5.10.xではエラーにならないようです。 (同じ環境において5.8.8では再現し、5.10.0にバージョンアップすると 再現しなくなり、再度5.8.8にバージョンダウンすると再現します) 本番機の環境が5.8.8で勝手にバージョンアップなどができないため、 5.8.8で正常に動作するようにするにはどうしたらよいでしょうか。 結構、無駄も多いと思いますので全く同じ動作をしながらより効率の いい書き方ができたらいいなと思います。 (なお、実際には使用しているけど上記では使用していない部分が 含まれていてその部分がない場合もエラーにならないようです)

    • ベストアンサー
    • Perl
  • サブルーチンの返値に配列のハッシュ

    いつもお世話になっております。 HTML::Templateを使用する為、サブルーチンの返値に配列のハッシュを入れたいと思っていますが、うまくいきません。 また、myの使い方が分からず、返値までの方法も若干気になります。 よろしくお願い致します。 use HTML::Template; @loop = &loop_make('aa<>ab<>ac','ba<>bb<>bc','ca<>cb<>cc'); my $template = HTML::Template->new(filename=>'sample.html'); $template->param(loop=>\@loop); print "Content-Type: text/html\n\n"; print $template->output; exit; sub loop_make{ @aaa = (); foreach $xxx (@_) { ($one,$two,$three) = split(/<>/,$xxx); push @loop, { one => $one, two => $two, three => $three }; } return \@aaa; }

  • オブジェクト指向処理

    以下のようにnew{}の中で作成したstrをsub{}の中で利用したいのですが、どうすればよいでしょうか? perlでOOPするにあたり、参考になるような良書がありましたら教えてください。 new { $this = shift; my ($s1, $s2, $s3) = @_; my str = $s1.$s2.$s3; } sub { $this = shift; print str #new{}の中で定義したstr }

    • ベストアンサー
    • Perl
  • perlの構文がおかしいようです。

    構文は以下の通りです。IF文のところがおかしいようですが、どこに間違いがあるのか教えていただけないでしょうか。 sub ippack { my ($a, $b, $c, $d) = @_; return ($a << 24) | ($b << 16) | ($c << 8) | $d; } sub ipunpack() { my ($n) = @_; return (($n>>24)&0xFF,($n>>16)&0xFF,($n>>8)&0xFF,$n&0xFF); } open (IN,"<useIP.txt") while(my $input = <IN>) { if ($input =~ /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+) ([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/){; my $n = &ippack($1,$2,$3,$4); my $m = &ippack($5,$6,$7,$8); $n = $n & $m; $m = ~$m & 0xFFFFFFFF; for(my $i = 0; $i <= $m; $i++) { print join(".", &ipunpack($n+$i))."\n "; } } if-else($input =~ /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/);{ print "$input\n"; } print "\n"; }

    • ベストアンサー
    • Perl
  • サブルーチン内のサブルーチン定義について

    サブルーチン内で定義したサブルーチンで、思い通りにならない挙動で困っています。 'test'を10万回繰り返す文字列の生成を行い、その文字列長を表示する関数を funcA とします。その生成過程では、自分の関数内で宣言した再帰関数 funcB を呼び出します。 #! /usr/local/bin/perl use strict; my $time0; for(my $i=0; $i<10; $i++){   $time0 = times();   &funcA();   print((times() - $time0). "\n"); # funcAに掛かった時間 } sub funcA {   my $buffer = '';   &funcB(1);   print length($buffer) . " : "; # $buffer の文字列長      sub funcB{     my $n = shift;     $buffer .= 'test';     return if($n==100000);     funcB($n+1);   } } この結果が、 400000 :3.063 0 :0.468 0 :0.594 0 :0.766 0 :0.859 0 :1.11 0 :1.187 0 :1.141 0 :1.343 0 :1.469 となり、初回以降 $buffer の長さが0となるのも不可解ですが、funcA の実行時間が増加していくのも理解できません. これを #! /usr/local/bin/perl use strict; my $time0; my $buffer; # 注1 $buffer をファイル内大域変数として宣言 for(my $i=0; $i<10; $i++){   $time0 = times();   &funcA();   print((times() - $time0). "\n"); } sub funcA {   $buffer = ''; # 注2 レキシカル変数宣言をやめた   &funcB(1);   print length($buffer) . " : ";      sub funcB{     my $n = shift;     $buffer .= 'test';     return if($n==100000);     funcB($n+1);   } } とすると、結果は 400004 :3.188 400004 :0.234 [以降、上にほぼ同じ] と文字列長は正しいものの,初回以降のfuncA実行時間が極端に減ります. 内部ではどういうことが起こっているのでしょうか.

    • ベストアンサー
    • Perl
  • Net::Telnetでタイムアウト時間が短い

    タイムアウト時間を確認するのに、以下のプログラムを実行したのですが、存在しないホストを指定してプログラムを実行しても3秒程度でタイムアウトしてしまいます。指定したタイムアウト時間(以下のプログラムでは100秒)待つにはどうすればよろしいでしょうか? お願いします OS:CentOS 5.1 perl: 5.8.8 Net-Telnet-3.03 ===== プログラム ===== #!/usr/bin/perl use Net::Telnet (); my $result; my $h = 'aa.bb.cc.dd'; my $u = 'my_name'; my $pass = 'my_pass'; my $p = '/[\$%#>] $/'; my $t = new Net::Telnet (Timeout => 100, Prompt => $p, Errmode => "return"); $result = $t->open($h); unless($result) { print "open ng\n"; exit; } else { print "open ok\n"; $t->login($u, $pass); print "login ok\n"; $t->print("exit"); }

    • ベストアンサー
    • Perl
  • IO-Socketで…

    最初に開かれた1つのソケットで、 サーバーから不定期に送られてくるデータを処理→表示しつつ、 ユーザーから入力があった場合にそのソケットへ送信するといったメッセンジャーを作ろうと思っているのですが、「入力待ちと受信待ちを同時に進める」という事がどうも上手くいってくれません… use threads;を使い、送信用・受信用と分けたのですが、やはりどちらか一方が止まってしまいます…。 どの様に書いたらよいのでしょうか… 何方かご教授下さい…。 use threads; use IO::Socket; ($test_socketを生成) sub send{ while($input = <STDIN>){ chomp($input); print $test_socket "$input"; } sub recv{ while(1){ if($receive = <$test_socket>){ print "$receive\n"; } } } my $sendthread = threads->new(\&send); $sendthread->join(); my $recvthread = threads->new(\&recv); $recvthread->join();

  • Parallel::ForkManager(2)

    前回の投稿で完全に書き間違えた部分がありそのままではよくわからないものになってしまっていたのですが、投稿し直しなどができなかったので再度投稿させてもらいます。 プログラムは use Web::Scraper; use WWW::Mechanize::Firefox; use Parallel::ForkManager; use URI; binmode STDOUT,":utf8"; sub func ; ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(); $year += 1900 ; $mon += 1 ; $File = "yuma-$year:$mon:$mday:$hour.txt" ; open (file,"> $File") or die 'fail to open file\n'; print "HOW MUCH PAGE\n" ; my $page = <STDIN> ; print "WITEING...\n" ; my $MAX_PROCESSES = 5; my $pm = new Parallel::ForkManager($MAX_PROCESSES); for ($i = 1;$i <= $page;$i++) { $pm->start and next; my $uri = URI -> new ("www.目的とするURL$i.html"); my $mech = WWW::Mechanize::Firefox->new(); $mech->get($uri) ; print file $s->scrape($mech->content) ; print file "\n" ; print file $r->scrape($mech->content) ; print file "\n" ; $pm->finish; } print "WITEID\n" ; my $s = scraper { process 'font',sen => 'TEXT'; result 'sen'; }; my $r = scraper { process 'div#content',ren => 'TEXT'; result 'ren'; }; close (file) ; です。 $i の順序でファイルへ書き込みをしていきたいのですが、前の処理が終わっていなかった場合に待つ方法がわからないので初心者レベルで教えてください。

    • ベストアンサー
    • Perl