foreachのワーク変数には参照が入る!!
配列変数をforeachで処理するときに、配列変数の要素をワーク変数(下のサンプルでは$value)へ格納しますが、これには、値でなく参照が入ります。
ですので、ワーク変数を編集すると、実は配列変数の要素を編集することになり、思わぬ結果が生じることがあるのです(経験者は語る)。
以下のNo.1では、@Nameの要素に対して、文字列『<br>』が外側のループ毎に一つ多く付加される(想定外)。
これを避けるためには、No.2のように一時変数にsubstr(元の値をコピー)して、その一時変数に対して、文字列『<br>』を付加します。
サンプル No.1
use strict; use warnings; print '◆No.1 foreachのワーク変数$valueをそのまま使う', "\n"; my $Name = ""; my @Name = ('aaaa(10)', 'bbbb(11)', 'cccc(12)', 'dddd(13)'); for (my $i = 0; $i < 3; $i++) { foreach my $value (@Name) { $value =~ s/(^.*)(\(.*$)/$1<br>$2/; # ワーク変数$valueの内容を編集する $Name = $Name . "<th>$value</th>"; } } print $Name, "\n";
処理結果 No.1(ループ毎に『<br>』が一つ多く付加されてしまう[異常])
C:\Documents and Settings\koike>perl No1.pl ◆No.1 foreachのワーク変数$valueをそのまま使う <th>aaaa<br>(10)</th><th>bbbb<br>(11)</th><th>cccc<br>(12)</th><th>dddd<br>(13)< /th><th>aaaa<br><br>(10)</th><th>bbbb<br><br>(11)</th><th>cccc<br><br>(12)</th>< th>dddd<br><br>(13)</th><th>aaaa<br><br><br>(10)</th><th>bbbb<br><br><br>(11)</t h><th>cccc<br><br><br>(12)</th><th>dddd<br><br><br>(13)</th>
サンプル No.2
use strict; use warnings; print '◆No.2 foreachのワーク変数$valueをsubstrして使う', "\n"; my $Name = ""; my @Name = ('aaaa(10)', 'bbbb(11)', 'cccc(12)', 'dddd(13)'); my $tmp_value; for (my $i = 0; $i < 3; $i++) { foreach my $value (@Name) { $tmp_value = substr($value, 0); # ワーク変数内の参照の元の値を一時変数にコピーする $tmp_value =~ s/(^.*)(\(.*$)/$1<br>$2/; # 一時変数の内容を編集する $Name = $Name . "<th>$tmp_value</th>"; } } print $Name, "\n";
処理結果 No.2(こちらは、ループしても必ず一つのみ付加される[正常])
C:\Documents and Settings\koike>perl No2.pl ◆No.2 foreachのワーク変数$valueをsubstrして使う <th>aaaa<br>(10)</th><th>bbbb<br>(11)</th><th>cccc<br>(12)</th><th>dddd<br>(13)< /th><th>aaaa<br>(10)</th><th>bbbb<br>(11)</th><th>cccc<br>(12)</th><th>dddd<br>( 13)</th><th>aaaa<br>(10)</th><th>bbbb<br>(11)</th><th>cccc<br>(12)</th><th>dddd< br>(13)</th>