• ベストアンサー

foreach内での$_の書き換え

数年前にハッシュのデータをforeachで取り出す時、$_をいじると、$_はハッシュのデータと直接つながっているので、ハッシュのデータ(keyは変わらずvalueのほう)が書き換わってしまうと聞き、実際にやってみて書き換わってしまった覚えがあります。 %hash = ("red" => "aka", "green" => "midori", "blue" => "ao", "black" => "kuro"); foreach (%hash){ print "$_<br>\n"; $_ = "modify"; } print "<hr>\n"; foreach (values %hash ){ print "$_<br>\n"; } ↓↓↓↓↓↓html↓↓↓↓↓↓↓ blue ao green midori red aka black kuro ------------------------------------ modify modify modify modify ↑となったはず 先日それを試してみたら書き換わりませんでした。 以前は確かに書き換わった覚えがあります。 perlの仕様が変わったのでしょうか。それとも私が何か間違っているのでしょうか。 詳しい方にお教えいただければと質問しました。 よろしくお願いいたします。

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

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

  • ベストアンサー
  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.2

> 最初に試したのはniftyのアットホームページのサーバーだったのですが、 あー、あそこのPerlは 5.003とか4のあたりの骨董品のままじゃなかったでしたっけ? しかも標準モジュールすらないという。 ということで5.005_04のソースを引っ張り出してビルドしてから試してみました。 blue<br> ao<br> green<br> midori<br> red<br> aka<br> black<br> kuro<br> <hr> ao<br> midori<br> aka<br> kuro<br> どうも途中で仕様が変わったみたいですね。 5.6とか5.8に上がったタイミングかなあ?

tackross
質問者

お礼

度々のご回答ありがとうございます。 な、なるほどぉ。 確かにniftyはperl5としか書いてなく、モジュールも使えません。 わざわざ試してくださったんですね。 >どうも途中で仕様が変わったみたいですね。 5.6とか5.8に上がったタイミングかなあ? 合点がいき、スッキリしました。 どうもありがとうございました。

その他の回答 (2)

  • kabaokaba
  • ベストアンサー率51% (724/1416)
回答No.3

ちなみに5.6でも$_は実体を共有してます. この手のことがあるので $_とか@_は値を変えないか 明示的にコピーですね

tackross
質問者

お礼

回答ありがとうございます。 そうですね。 一見、別の器に入れているように見えて 実は仮の姿と言う感じですね。 早合点で質問してしまいましたが、 これはこれでまた勉強になりました。 ありがとうございました。

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.1

今手元の5.8.8と5.10.0で試しましたけど、 green midori black kuro blue ao red aka ------ modify modify modify modify こんな感じですが。 テストしたときに何か勘違いしてたりしませんか?

tackross
質問者

お礼

回答ありがとうございます。 回答を見て、あわてて他のサーバー(land.to)で確かめて見た所、確かに書き換えられてました。私の早合点でした。 ただ、新たな疑問が・・・。 最初に試したのはniftyのアットホームページのサーバーだったのですが、相変わらずこちらで試すとデータが書き換わりません。 なぜなんでしょうか・・・うぅ。 ありがとうございました。

関連するQ&A

  • perlでくじ引きプログラムを作りたい

    箱の中に、 akaが14個 aoが21個 kiiが443個 以下続く(__END__以下) という様にさまざまな色のボールが箱に入っているとします。 そこから、80個だけ取り出した場合、 aka=4 ao=9 aka=4 以下続く という様に表示させたいのですがどのようにすればよいでしょうか? ネット上で見つけた色々なプログラムをくっつけてはみたのですがいまいちです。 特に、ballの数がakaが14個ではなく、akaが1000000個、ao300000個のように膨れるとメモリも多く要りそうですし、時間もかかってしまいます・・・ もっとうまくやるやり方があると思うのですが、どうしても思いつきません。 どなたか、教えていただけ無いでしょうか? 宜しくお願い致します。 #!/usr/bin/perl print "Content-Type: text/plain\n\n"; my $cnt = 80; my ($line,@array,@data,$data); foreach $line (<DATA>){ @array = split(/\t/,$line); for(1..$array[2]){ #ここの部分がかなり問題あり・・・ $data[$datacnt++]=$line; } } srand; for (my $i = @data; --$i; ) { my $j = int rand ($i + 1); next if $i == $j; @data[$i, $j] = @data[$j, $i]; } foreach(0..($cnt-1)){ #とりあえず表示させる。 print $data[$_]; } #同名を集計して表示させるプログラムを作る予定 #空白はタブ区切りです。 __END__ ball aka 14 ball ao 21 ball kii 443 ball midori 112 ball shiro 122 ball orenji 1

    • ベストアンサー
    • CGI
  • ハッシュの中身の表示

    ハッシュの中身の確認ができなくて困っています。 下記のような実行文においてです。 当然、test の戻り値は、スカラーとハッシュです。ハッシュを戻すときには参照渡し記号の\もつけています。 my ($return_code, %hash_data) = test(); 表示しようとすると、 Hash(0x5b04) のような表示にしかなりません、、 (試した表示方法は、下記4つです。) (環境は、WindowsXP上での、ActivePerl-5.10.0.1004 です。) foreach $key ( keys( %Hash ) ) { print "キー値 : $key\n"; print "値 : $Hash{$key} \n " } while ( ( $key , $value ) = each %Hash ){ print "キー値 : $key\n"; print "値 : $value \n " ; } use Data::Dump qw(dump); print dump(\%hash); #print %display_test; 宜しくお願いします。

    • ベストアンサー
    • Perl
  • Ruby 2次元のハッシュ

    Rubyで2次元のハッシュを扱いたいです。 perlで書くと以下のような感じです。(最近perlに疎遠なので自信無いですが^^;) hash{$key1}{$key2}=$value; foreach $key1 (keys %hash){ foreach $key2 (keys %{$hash{$key1}}){ print "$hash{$key1}{$key2}\n"; } } Rubyだとどんな感じになりますか?

  • 動的ハッシュを作って取り出したいのですが・・・

    お世話になります。 フォームから送られてくるデータを動的に作ったハッシュで参照出来るように取り組んでるんですが、思ったように出来ず思い悩んでおります。 どうすれば、意図した形でデータを取り出すことが出来ますでしょうか my %FORM = ( 'd01' => 'あ', 'd02' => 'い', 'd03' => 'う', 'd04' => 'え', 'd05' => 'お', 'd06' => 'か', 'd07' => 'き', 'd08' => 'く', 'd09' => 'け', 'd10' => 'こ', ); for(sort { $FORM{$a} cmp $FORM{$b} } keys %FORM){ print "$_ = $FORM{$_} \n"; } $list="d01,d02,d03,d04,d05,d06,d07,d08,d09,d10,"; $i=-1; foreach (split/,/,$list){ $i++; $hash{$_}=$i; } for(sort { $hash{$a} <=> $hash{$b} } keys %hash){ print "$_ = $hash{$_} \n"; $view = ${"FORM$_"}; print "$view\n"; }; 最後のprint "$view\n";箇所で、 $list="d01,d02..." を split/,/,$list したので、 $FORM{d01} $FORM{d02} となるようにして、 「あ い う え お」と取り出したいのです。 ご教授のほど、よろしくお願い致します。

    • ベストアンサー
    • Perl
  • functionとforeachでメール送信

    こんにちは。前にも質問をさせて頂いたのですが・・・ HTMLのメールフォームからPOSTでデータを受信してクライアントとユーザーの両方にメールを送るようなプロゴラムを記述しています。 データの受け取りからメールの送信のスクリプトを function message(){ foreach($_POST as $key => $val){ print( $key .":" .$val. "<br>"); }; }; $message= " テスト送信 <br>"; $message.= message(); if(mail("クライアントのメールアドレス" , "テストメール", $message, $head)&& mail(message(34) , "テスト確認メール", $message, $head)){ print("・・・"); }else{ print("ご注文メール送信に失敗しました。<br />\n"); print("再度ご注文フォームより注文して下さい。\n"); print("<a href=\"#\">戻る</a>"); }; としています。message(34)はユーザーのアドレスを取得しています。 しかし実行すると画面にPOSTで取ってるデータが2回表示され肝心のメールは クライアントには " テスト送信 と本文に表示されてユーザーにはメールが届きません。 質問が2つですみませんが、 1、functionで関数を作りforeachでデータを取得しメールで送信するというやり方は無謀なのでしょうか? もしできるのでしたらやり方を教えて頂けないでしょうか? 2、メールの本文にある"を消すにはどうしたらいいのでしょうか? かれこれ1週間近く悩んでいるのですが、一向にできそうにありません・・・。皆さんの知恵と知識をお借りできたらなと思います、どうかよろしくお願いします。 他に何かいる情報があれば教えて下さい。分かる範囲で補足していきます。

    • ベストアンサー
    • PHP
  • 参照配列の要素数の求め方は?

    リファレンス配列の要素数は、$#では求められないのでしょうか? ------------------------------------- foreach $i(0 .. 3){ $hash->[$i] = $i * 100; } print "\%hashの要素数->$#hash\n"; $ref = \%hash; print "\%{$ref}の要素数->$#{$ref}\n"; -------------------------------------

    • ベストアンサー
    • Perl
  • JavaのString配列で隣り合うデータを順に比較する

    JavaのString配列で隣り合うデータを順に比較する Javaのバージョンは1.5です。 配列の隣り合うデータを順に比較し、異なるデータがあったら フラグのカウントを+1したいです。(下記の配列の場合のカウントは3になります) 特に並べ替えは行いません。 String[7] color = {"aka","aka","aka","ao","ao","aka","kuro"} 配列のデータ数は固定なので、 for文などのループ処理で比較を繰り替えすものだとは思うのですが、 うまくカウントできません。 一つ目の不一致(3つ目と4つ目の比較)が見つかった後、 次の比較へ移るところ(4つ目と5つ目の比較)がうまくいきません どのように記述すればよいでしょうか?

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

    ハッシュのキーに対応する値の数の多さ順で表示させたいと考え、下記の所まで試行錯誤しておりますが、どうにも思ったようにソートできずにおります。 #!/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
  • PDOのバインドをforeachでまとめて処理したいができません…。

    いつもお世話になっております。 PHP5.2.5 --------------------------- DB(フィールドは以下3項目) ・id(primary key) ・color ・num --------------------------- //DBにインサートするデータ群(配列に格納してある) $insert_array = array('color'=>'red','num'=>6); //================================================== // *フィールド名とそれに対応するデータをバインドする。 //================================================== //================================================== // *バインド:方法1 //================================================== foreach($insert_array as $field => $value){  //確認処理  //echo $field.'<br/>';  //echo $value.'<br/>';  //バインド(foreachで、1つずつバインドしていく)  $stmt->bindParam(':'.$field,$value); } //================================================== // *バインド:方法2(↓こちらだと上手くいく。) //================================================== /* $stmt->bindParam(':'.'color',$insert_array['color']); $stmt->bindParam(':'.'num',$insert_array['num']); */ //================================================== // *バインド後、「$stmt->execute();」した結果 // *DBにインサートされたものをprint_r()にて確認 //================================================== ★方法1 Array ( [id] => 15 [color] => 6 [num] => 6 ) //--------------------------- ★方法2 Array ( [id] => 16 [color] => red [num] => 6 ) //--------------------------- ★方法1の結果の、「 [color] => 6」って一体…?! 方法2のように、同じバインド処理を手書きで繰り返す分にはうまくいくのですが、 方法1のようなforeachでまとめて処理するやり方だとうまくいきません。 方法1の問題箇所をどなたか教えて下さい。 宜しくお願い致します。

    • ベストアンサー
    • PHP
  • 当てはまらなかったら、エラー処理

    いい考えが思い付きません。 是非とも知恵を貸してください… CGIです。 フォームで入力された文字列とハッシュ内のキーを比較し、 一致すれば値を出力、すべてに当てはまらなかったらエラーを返すというのをやりたいのですが、 $value にフォームからの文字列が入っているとします。  $value = "1";  %hash = ("1" => "A", "2" => "B", "3" => "C"); if (&search()) {   last;  } else {   &error("一致しません"); } exit; #---------------------------------- sub search {  foreach $key(keys %hash) {   if ($key =~ /$value/) {    print "--$hash{$key}\n";   }  } } #---------------------------------- sub error {  print "error $_[0]\n"; } 結果は、 --A error 一致しません でした。 $value をキー以外にするとちゃんとエラーになるんですよ。 いい方法はないでしょうか?

    • ベストアンサー
    • Perl