この文中の$_の正体について

[上に] [前に] [次に]
PERL大好き 2000/03/29(水) 23:01:58
$li=undef;
@tags=("1st","2nd","3rd");
foreach (@tags){
   if(/^2nd/){
      push(@body,$_);
      $li=1;
   }elsif($li){
      push(@foot,$_);
   }else{
      push(@head,$_);
   }
}

print "@head\n";
print "@body\n";
print "@foot\n";

この以上のプログラムですが結果は@headは1st,@bodyは2nd,@footは3rdとなりますが$_の正体すなわち最初の2ndとマッチしてものがパターンマッチの特殊変数$&となりますがそれ以外@footの$_の正体が$',@headの$_の正体が$`だと思っていたのですが違うみたいですのでこれらの$_の正体がおわかりなる方ぜひおしえていただけば光栄です。よろしくお願いいたします。具体的に明確にお願いします。

2000/03/30(木) 00:17:51
根本的に勘違いされてるのではないでしょうか?

$&#最後にマッチしたパターンが入っている
$`#最後にパターンマッチした物より前の文字列
$'#最後にパターンマッチした物より後の文字列

つまるところ文字列の前後が入るのであって,配列の並びは関係ない.
さらに/^2nd/の場合絶対に$'はセットされない.

#!/usr/local/bin/perl

$str = "1st2nd3rd";
$str =~ m/2nd/;
print "Content-type: text/html\n\n";
print "\$` = $`<BR>";
print "\$& = $&<BR>";
print "\$' = $'<BR>";

だから$_にはきちんと順番に1st,2nd,3rdが入ったはずです.
と,思うのですがどうでしょう?

#未定義値を持たせたい場合はundef $li;とする物では?
#位置文が長くて読みにくいです.

2000/03/30(木) 01:09:43
訂正:
>さらに/^2nd/の場合絶対に$'はセットされない.
 さらに/^2nd/の場合絶対に$`はセットされない
が正しいです

さだひろ [E-Mail] 2000/03/30(木) 02:09:44
foreach文なら,$_の正体は()内の配列,@tagが順に入るでしょう.
最初に$tags[0],すなわち'1st'が$_にセットされ,
if(/^2nd/)で外れ,elsif($li)で外れ,elseのブロックが実行される.
次に$tags[1],すなわち'2nd'が$_にセットされ,/^2nd/ が真になるので{push(@body,$_); $li=1;}が実行される.
最後に$tags[2],すなわち'3rd'が$_にセットされ,/^2nd/は偽だが,$liが真になるので @footに'3rd'が入る.

これだけのことではないでしょうか?
$&, $', $`なんてコードに入っていないものが関与するわけがありません.

さだひろ 2000/03/30(木) 02:29:41
補足.

$li=undef;
@tags=("1st","2nd","3rd");
foreach (@tags){
   if(/^2nd/){
      push(@body,$_);
      $li=1;
   }elsif($li){
      push(@foot,$_);
   }else{
      push(@head,$_);
   }
   print(join(':',($_,$&,$',$`)),"\n");
}

を実行すると,
1st:::
2nd:2nd::
3rd:2nd::
となります.
このことからわかりますように,マッチしないとき$&は置き換わりません.

>#未定義値を持たせたい場合はundef $li;とする物では?
$li=undef; でも未定義値が代入されますよ.
関数undefの返す値は常にスカラーの未定義値ですから.

さだひろ 2000/03/30(木) 02:40:12
また補足
>さらに/^2nd/の場合絶対に$`はセットされないが正しいです
これも違います.

@tags=("1st","2nd","3rd");
foreach (@tags){
   /^2nd/;
   print (defined $& ? 1 : a);
   print (defined $' ? 2 : b);
   print (defined $` ? 3 : c);
   print "\n";
}

の結果は

abc
123
123

ですから,最初のマッチングが不成功のときは
$&,$',$`は未定義値のままですが,
2回目にマッチした時点では &' にも &` にも
空文字列がセットされます.未定義値ではありません.

さだひろ 2000/03/30(木) 02:53:58
またまた補足

@tags=("1st","2nd","3rd");
foreach (@tags){
   /^2nd/;
   print (defined $& ? 1 : a);
   print (defined $' ? 2 : b);
   print (defined $` ? 3 : c);
   print "\n";
}
#このあとでは$&,$',$`は未定義値に戻る
   print (defined $& ? 7 : A);
   print (defined $' ? 8 : B);
   print (defined $` ? 9 : C);

の結果は

abc
123
123
ABC

ですから,$_が'3rd'の時点では$&,$',$`は生きていますが,
foreach文のブロックが終わった時点で $&,$',$`のスコープが変わるので,
最後の三行の位置ではすべて未定義値になっています.

2000/03/30(木) 05:04:31
#主題とは関係無いんですけど・・・
>>さらに/^2nd/の場合絶対に$`はセットされない
>空文字列がセットされます.未定義値ではありません.

確かに,あなたは正しい.間違っていない.
たださ,こう言うときいちいち空文字列がセットされますっていわないといけないのですか?
そこまで気を使うべき?
こういうケースで未定義値がセットされると思う人は居ないでしょう?
#少なくとも"さらに/^2nd/の場合絶対に$`は未定義値がセットされます"といったら駄目出しされてしかるべきだと思うんだけど

そのためにわざわざ3回も投稿してくれたわけですし訂正しておきます.
私の表現は適切ではありませんでした.
それを認めここに訂正します.
>さらに/^2nd/の場合絶対に$`はセットされない
 さらに/^2nd/の場合絶対に$`は空白文字列以外セットされない

PERL大好き 2000/03/30(木) 21:56:27
[[解決]]
とても大きな勘違いしていました。どうもありがとうございました。

[上に] [前に] [次に]