電子書籍の厳選無料作品が豊富!

Perlのハッシュのリファレンスを使ってみたいと
思いましたがうまく動きませんでした。
よろしくお願い申し上げます。

ファイル(inifile.txt)からPerlで
UserNameとTargetの値を
hanako,11111
tarou,2222
の様に出力したいのですが。

tarou,2222
tarou,2222
と成ってしまいうまくいきません。


--inifile.txt----------
Mode=True
UserName=hanako
DeleteMode=True
Target=11111
TouchDateMode=False


Mode=True
UserName=tarou
DeleteMode=True
Target=2222
TouchDateMode=False
--------------------

--test.pl---

while($line=<DATA>) {
      # my $info={}; #これを入れるとTargetは入りました
chomp($line);
if($line=~/UserName/){
   $line=~s/UserName=//;
   $info->{UserName}=$line;
}elsif($line=~/Target/){
  $line=~s/Target=//;
  $info->{Target}=$line;
push @$infos,$info;
}
}

foreach my $k(@$infos){
my @line2=(
$k->{UserName},
$k->{Target});
print join(",",@line2)."\n";
}

__END__
Mode=True
UserName=hanako
DeleteMode=True
Target=11111
TouchDateMode=False


Mode=True
UserName=tarou
DeleteMode=True
Target=2222
TouchDateMode=False

A 回答 (1件)

$info が宣言されていないので、グローバル変数として扱われます。


それを $info->{} として使った時点で
$info = 無名のハッシュ(これをH0とする)のリファレンス
となります。以降、 $info->{} は H0 を操作することになります。
while($line=<DATA>) {
が終った時点で、H0は最後に操作した内容となります。

push @$infos,$info;
では、 @$infos に $info 、つまり「H0のリファレンス」 を追加します。
よって、実行したら
$infos = [ 「H0のリファレンス」,「H0のリファレンス」 ]
という状態になります。
そんため
foreach my $k(@$infos){
では、「 H0のリファレンス」への処理を2回繰り返すことになります。
H0の内容は、「最後に処理された状態」ですから、最後のtarou,2222 だけが繰り返されます。


このような現象は、リファンレンスを使う言語ではよくあることです。
「浅いコピー」「深いコピー」といった用語が使われていますので、これで検索してみましょう。


対策は、 @$infosに 「H0と同じ内容の別のハッシュ」をpushすることです。
例えば
push @$infos, {%$info};
# %$infoと H0を展開したものを新しい無名のハッシュにして、それをpushする
など。


> # my $info={}; #これを入れるとTargetは入りました

この方法では、 ループ毎に新しいハッシュが用意されます。
そのため、UserとTargetのときとでは、「別のハッシュ」への操作となります。
そのため、 pushするときの$info、すなわち Targetだけが入ったハッシュが $infosに追加されます。
    • good
    • 0
この回答へのお礼

ありがとうございます!
意図したとおりの動きになりました!

新しいリファレンスを作る?とういことですか。
大変勉強になりました他に応用していきたいと思います。

お礼日時:2015/06/06 12:02

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!