• ベストアンサー

$bは表示されない??

######## @a=(1,2,3,4,5,6,7); foreach $b (@a[0..3]){ $b++; } print @a; print "\n"; print $b; ######## とした時に、$bが表示されません。なぜなのでしょうか??5が表示されるのかなと思っていたのですが・・・ でも ######## @a=(1,2,3,4,5,6,7); for(@a[0..3]){ $_++; } print @a; print "\n"; print $_; ######## とすれば、$_は表示されます。 私はまだPerlもプログラミングも初心者なので、誤解してるところがあったらご指摘ください。 よろしくお願いしますm(_ _)m

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

  • ベストアンサー
回答No.2

ループスコープ for:ループ変数は設定された最後の値を保持 foreach:変数はループより前に持っていた値に戻る my $i=30; for ($i<0; $i<10; $i++){} print $i; →$iは10と表示 my $i=30; foreach $i (1..10){} print $i; →$iは30と表示 forとforeachは同じものとみなされますが(実際そうですが)、 この一点だけ扱いが異なっています(他にもあるかもしれませんが(^^;) 今回$bが無かったのは、foreach前に$bが無かったからかと。 次のforの例では、for使ってますので、最後の値が残るわけです。 いずれにせよ、ループ変数をそのまま使うようにプログラミングするのは バグの元ですので、明示的に他の変数に格納してやるといいと思いますよ。 (use strict;していれば事前に警告がでるので回避できるとも思います) #手っ取り早くワンライナー perl -le 'my $i=30; for($i=0; $i<10; $i++){} print $i' perl -le 'my $i=30; foreach(1..10){} print $i'

rousei
質問者

お礼

ありがとうございました!またお願いします♪

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (1)

noname#25358
noname#25358
回答No.1

 お使いの Perl がどんなバージョンかは分かりませんが、ActivePerl の場合は後者も print $_; は働かないようです。  この原因として考えられるのは foreach の仕様です。  foreach の $b の中に入っているのは、実は値ではなくリファレンスだということは、(何となくかもしれませんが)お分かりかと思います。  ゆえに、値を書き変えると配列の値が更新されてしまうわけですよね。  で、インタプリタの開発者が、「ループを抜けたあとで $b に余計な値を入れて配列の値が変わってしまわないように」との考えで、リファレンス化を解除しているのかもしれません。  実際、その方が利便性がありそうですし。  rousei さんがお使いの Perl で後者が動いたのは、Perl のバグか、でなければ「$_ は最後に省略された変数である」というコンセプトに基づく仕様であると思われます。  ActivePerl はラクダの人が開発したわけじゃないので、そのへん、コンセプトより利便性を重視していると考えられるわけです。

rousei
質問者

お礼

ありがとうございます^^ またよろしくおねがいします

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • perl で環境変数を表示できない

    perlの初心者です。下記のCGIを実行しましたが、全く表示しません。 最初の「環境変数」と言う文字も表示しません。 どこか初歩的なエラーがあると思いますが、わかりませんので質問させていただきます。 --- #!/usr/local/bin/perl print "Content-type: text/html", "\n\n"; print "<HTML><BODY>", "\n"; print "<H1>環境変数</H1><HR>", "\n"; foreach my $key( keys %ENV ){ print "$key: $ENV{$key}<BR>", "\n"; } print "<HR>", "\n"; print "</BODY></HTML>", "\n";

    • ベストアンサー
    • Perl
  • エラー表示

    CGIがエラーを出すと、サーバーが500番エラーを表示しますよね。 そのページを.htaccessのErrorDocumentを使って、自分で定義したものにできたのですが、そのエラーページをCGIにして、どこかにエラーになったページが吐いたエラー出力が入ってないかと思ったのですが、入ってないのでしょうか? -------- #!/usr/bin/perl # hoge.cgi # エラーするCGI die "hoge!"; -------- #!/usr/bin/perl # error.cgi # 500エラーページなCGI print "$_: $ENV{$_}<br>\n" foreach(sort keys %ENV); # ここでもない print foreach(<STDIN>); # ここでもない print foreach(<STDERR>); # ここでもない print ・・・どこかに "hoge!" が入ってないでしょうか? -------- # .htaccess ErrorDocument 500 /error.cgi Apache/1.3.24 Server perl 5.005_03 built for sun4-solaris

    • 締切済み
    • CGI
  • 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);    }  } 上が一番早く下に行くほど遅いですがあまり違いはありません。 よろしくお願いします。

  • Perlで1~10まで全部足す。簡単に書くには?

    題名のとおりなんですが。 Perlで1~10まで全部足すのに、 1番簡単に書いたらどんな感じなるでしょうか? (一回足すごとに結果は表示) 私は全然浮かばず、 $a = 1 print "$a\n" $b = $a + 1 print "$b\n" $c = $b +2 " …続く こんな感じのお粗末なものを書きました。 whileやforを使えばもっと簡単に書けると思いますが、 どなたかご存知でしたら教えてください。

    • ベストアンサー
    • Perl
  • eachとイテレーター

    each関数について質問させていただきます。perl5.8.0です。 eachに渡す引数を、ハッシュ“変数”ではなくハッシュ記法を直接指定する方法はないでしょうか。 具体的には、 %hash = (a=>1,b=>2); while (($k,$v)=each %hash) { ~ ではなく、 while (($k,$v)=each (a=>1,b=>2)){ ~ というように、eachに直接キーと要素を渡したいのです。 以下のようにいろいろ試したのですが、うまくいきません。 【1】 perl -e 'while (($k,$v)=each (a=>1,b=>2)){print "$k:$v\n";}' Type of arg 1 to each must be hash (not list) at -e line 1, near "2)" Execution of -e aborted due to compilation errors. 【2】 perl -e 'while (($k,$v)=each %{a=>1,b=>2}){print "$k:$v\n";}' syntax error at -e line 1, near "%{" Execution of -e aborted due to compilation errors. 【3】 perl -e 'while (($k,$v)=each %{(a=>1,b=>2)}){print "$k:$v\n";}' (何も出力されない) 【4】 perl -e 'while (($k,$v)=each %{{a=>1,b=>2}}){print "$k:$v\n";}' a:1 a:1 a:1 a:1 : (無限ループ) 予想では【3】の書き方が正しいような気がしましたが出力されず、そして【4】は少なくとも参照はできているようなのに、イテレーターが正しく動作していないような感じです。 (そもそもイテレーターというのは変数じゃなく無名ハッシュのようなものでも有効なのでしょうか?) また、試しにkeysで同じことをしてみると、 【5】 perl -e 'foreach (keys (a=>1,b=>2)){print "$_\n";}' Type of arg 1 to keys must be hash (not list) at -e line 1, near "2)" Execution of -e aborted due to compilation errors. 【6】 perl -e 'foreach (keys %{a=>1,b=>2}){print "$_\n";}' syntax error at -e line 1, near "%{" Execution of -e aborted due to compilation errors. 【7】 perl -e 'foreach (keys %{(a=>1,b=>2)}){print "$_\n";}' (何も出力されない) 【8】 perl -e 'foreach (keys %{{a=>1,b=>2}}){print "$_\n";}' a b keysでは【8】が期待どおりの動作をします。 どうぞよろしくお願いいたします。

    • ベストアンサー
    • Perl
  • perl localhostでgifを表示するには

    超初心者からプログラムを初めて1週間、 プログラム言語にはperlを使用しています。 mac os x です。 perlの教科書読みながら、アクセスカウンタを作ろうとした所、 何故かgif画像が表示されません。 ネットの素材置き場からとってきましたが、パソコン自身、gif自体は認識してくれてます。 ただ、それをperlに組み込んで使おうとすると、表示されません。 ブラウザはfirefoxとsafariで試しましたが、両方認識してくれませんでした。 ちなみにソースは ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー #!/usr/bin/perl print "Content-type: text/html\n\n"; print "<HTML>\n"; print "<HEAD><TITLE>アクセスカウンタ2</TITLE></HEAD>\n"; print " <BODY>\n"; print "<H1>test</H1><HR>\n"; if ( open ( FH , "count.txt")){ $cnt = <FH>; close( FH ); $cnt++; print"<CENTER>\n"; foreach $fld (split (// , $cnt)){ print "<IMG SRC=\"${fld}.gif\">"; } print"</CENTER>\n"; if ( open(FH, ">count.txt" )){ print FH $cnt; close(FH); } else { print "ファイルの書き込みオープンに失敗しました。\n"; } } else { print "ファイルの書き込みオープンに失敗しました。\n"; } print "</BODY>\n"; print "</HTML>\n"; __END__ ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー です。 テキストファイルを確認しているので、 perl 自体の活動と、アクセスのログ?自体は正常に動いているみたいです。 お願いします。 助けてください!

    • ベストアンサー
    • Perl
  • 1_1から1_5へカウントアップ後、2_1から1_5へカウントアップしたい

    お世話になります。 題名にあります通りなんですが、1_1から1_5にカウントアップしたら 2_1から2_5へとカウントアップするようなスクリプトを考えているのですが 下記の例ですと、1111122222333334444455555となってしまいなす。 どなたか良きアドバイス頂けないでしょうか。宜しくお願いします。 @list = (0, 1, 2, 3, 4, 5); foreach $b(@list) { for ( $a = 1 ; $a <= 5 ; $a++ ) { print ""; print "$a_$b\n" ; } }

    • ベストアンサー
    • Perl
  • TABを表示させる方法

    以前のテキストファイルのhtmlタグ<>を文字として表示されるに続いての質問ですが、 #!/usr/bin/perl main:{ $file = 'use1.txt'; print "Content-type: text/html\n\n"; print "<HTML><BODY>\n"; print "<TITLE>表\示</TITLE>\n"; open( FH, $file) or die "Can't open"; foreach( <FH> ){ $_ =~ s/</</g; $_ =~ s/>/>/g; print $_ ."<br>"; } close(FH); print "</BODY></HTML>\n"; } 表示するのにTABが抜けて、全て左詰めという感じになります。 TABを表示させるにはどうしたら宜しいのでしょうか? よろしくお願いします。

    • ベストアンサー
    • Perl
  • 静的ハッシュの配列のキーに対応する値の数の多さ順で表示させたい

    ハッシュのキーに対応する値の数の多さ順で表示させたいと考え、下記の所まで試行錯誤しておりますが、どうにも思ったようにソートできずにおります。 #!/usr/bin/perl use strict; my(%a, $i, $j ,$allarray ,@keys ,@keys2 ,%hash ,%files ,$a_mumei_ref ,$key ,$value ,@value ,$x ,$files); # ハッシュの配列を静的に作る %a = ( '0' => [ qw(0) ], '1' => [ qw(1 1) ], '3' => [ qw(3 3 3) ], '7' => [ qw(7 7 7) ], '2' => [ qw(2) ], '4' => [ qw() ], '5' => [ qw() ], '6' => [ qw() ], '8' => [ qw(8 8) ], '9' => [ qw(9) ], ); @keys = sort { $hash{$b} <=> $hash{$a} || length($b) <=> length($a) || $a cmp $b } keys %a; #ハッシュのキーを数字順で表示 foreach (@keys){ print $_ ."\n"; } # 静的に作ったハッシュの配列を取り出してみる foreach $i (sort keys %a) { for ($j = 0; $j <= scalar(@{$a{$i}})-1; $j++) { print '$a{'. $i. '}['. $j. ']='. $a{$i}[$j]. ' '; } $allarray=scalar(@{$a{$i}})-1; print "No$i:kosuu:$allarray"; print "\n"; #配列の値の個数を調べその配列を作成 my($a_mumei) = $allarray; $a_mumei_ref = \$a_mumei; $files{"$i"}=($i,$a_mumei_ref); } #each関数で%filesの中身を表示 while ( ( $key , $value ) = each %files ){ print "key:$key value:$$value\n" ; } #試行錯誤 foreach $x (sort { $files{$b} <=> $files{$a} } keys %files){ print "$x => $files->{$x}\n"; } @keys2 = sort {$hash{$a} <=> $hash{$b}} keys %files; #@keys2 = sort { $hash{$b} <=> $hash{$a} || length($b) <=> length($a) || $a cmp $b } keys %files; #@keys2 = sort { $hash{$a} cmp $hash{$b} } keys %files; print "@keys2\n"; print "\n"; __END__; 私のイメージしておりますのは、ソートした結果がハッシュのキーに対応する値の数の多さ順で下記のように表示させたいのですが、 どのようにすれば可能でございますか、ご教授願えませんでしょうか key:3 value:2・・・この場合valueは配列の個数 key:7 value:2 key:8 value:1 key:1 value:1 key:9 value:0 key:2 value:0 key:0 value:0 key:6 value:-1 key:4 value:-1 key:5 value:-1

    • ベストアンサー
    • Perl
  • ファイルを読込んで文字列置換後にブラウザに表示

    Perl超初心者です。 ユーザがブラウザのフォームに名前を入力し送信したら、「入力内容はこれでいいですか」という確認画面を表示したいのですが、s///を用いる置換の部分が、どこにどう書けばよいか分かりません。 以下のスクリプトは、ファイルを読み込んでブラウザに返し表示するものです。(ちゃんとブラウザに表示されます) 具体的に、このスクリプトの中のどこにs///を書けばよいのでしょうか。ご教示ください。 sub testComment { open(IN, "./sample.htm"); @file = <IN>; close(IN); print "Content-type: text/html\n\n"; foreach (@file) { print $_; }

    • ベストアンサー
    • Perl
HL-L2365DW 連続印刷が2枚で止まる
このQ&Aのポイント
  • HL-L2365DWの連続印刷で2枚で止まる問題について
  • MacOS BigSur ver11.3環境で無線LAN接続しています
  • 問題が解決しない場合はブラザーサポートに連絡してください
回答を見る