Atsulabo
@Atsulabo (アツ)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

正規表現 後方参照が理解できない

Q&A

Closed

解決したいこと

正規表現の後方参照に関するプログラムで、
なぜこうなるのかが理解できない。

発生している問題・エラー

これはプログラミング第3版p115にあったコードを修正してマッチしたものがわかるように出力させたものです。

index.php
<?php

preg_match("/([[:alpha:]]+)\s+\\1/","Paris in the the spring",$m);
print "<br>";
echo '$m[0]='. $m[0];
print "<br>";
echo '$m[1]='. $m[1];

?>

出力は
\$m[0]=the the
\$m[1]=the
となるのですが、
上記の正規表現の意味は、
([[:alpha:]]+)が、どの大文字小文字を含むアルファベットでもよいからそれが1文字以上、
\s+が、スペースが1文字以上、
となるので、スペースも含むと、第1にマッチするのは Paris のはずです。
\1が、バックスラッシュはエスケープで、\1、つまり後方参照となるのですが、
この場合、考えると、次にマッチするのはtheじゃなくて、in じゃないのか?と思うので、
なぜこうなるのかがわかりません。

自分で試したこと

ひとまず、\1をけして、\s+までにしてみて出力してみました。

index.php
<?php
//preg_match("/([[:alpha:]]+)\s+\\1/","Paris in the the spring",$m);
preg_match("/([[:alpha:]]+)\s+/","Paris in the the spring",$m);
print "<br>";
echo '$m[0]='. $m[0];
print "<br>";
echo '$m[1]='. $m[1];

?>

出力
\$m[0]=Paris
\$m[1]=Paris

これもこれで、$m[1]は inになるんじゃないのか?と思っているので
ますますわからなくなっています。。。

大変申し訳ありませんが、皆様の力をお貸しいただけると幸いです。

0

2Answer

preg_matchの仕組みに関する部分についてです。
preg_matchの第3引数は次のようになります。

matches を指定した場合、検索結果が代入されます。 $matches[0] にはパターン全体にマッチしたテキストが代入され、 $matches[1] には 1 番目のキャプチャ用サブパターンにマッチした 文字列が代入され、といったようになります。

そしてpreg_matchは1度しかマッチしません。

$m[0]=Paris
$m[1]=Paris
これもこれで、$m[1]は inになるんじゃないのか?

最初にマッチした全体のテキスト「Paris 」が$m[0]に入り、
サブパターンにマッチした「Paris」が$m[1]に入ります。
1度しかマッチしないので「Paris 」以降は入りません。

繰り返し検索する場合はpreg_match_allを使用します。

0Like

Comments

  1. @Atsulabo

    Questioner

    ありがとうございます。
    \1を消したところのほうですね。
    ([[:alpha:]]+)\s+に最初にマッチした全体のテキストは
    Paris。
    次にサブパターン、つまり([[:alpha:]]+)にマッチするテキストは
    結局同じParisになる、
    というわけですね。
    理解できました、ありがとうございます。

    ただ、1つめの後方参照の謎はまだ解けず。。。
    なぜ、the theという結果になるのか。。。

    キャプチャされたテキストはおそらくParisになると思うんですが、
    ここからどうやってthe theにマッチするのかがわからないです。。。

後方参照

後方参照は、カレントの対象文字列においてキャプチャ用サブパターンが 実際にマッチした文字列にマッチします。サブパターンがパターンとして マッチし得るものではありません。すなわち、パターン

 (sens|respons)e and \1ibility

は、"sense and sensibility" および "response and responsibility" にマッチしますが、 "sense and responsibility" にはマッチしません。

([[:alpha:]]+)は最初に「Paris」にマッチしますが、その段階で/(Paris)\sParis/になる、と考えればどうでしょうか?
もちろんこれはマッチすることはありません。
次は/(in)\sin/ですが、これもマッチせず。
そして次の/(the)\sthe/がマッチします。

ちなみに、

([[:alpha:]]+)\s+に最初にマッチした全体のテキストは
Paris。
次にサブパターン、つまり([[:alpha:]]+)にマッチするテキストは
結局同じParisになる、

$m[0]はスペースも入っているので、同じではありません。
echoよりもvar_dump($m)すると分かりやすいですよ。

0Like

Comments

  1. @Atsulabo

    Questioner

    おーーー!
    ありがとうございます!
    やっとわかりました(T ^ T)
    なるほど、全体で考えればよかったんですね。。。
    いやあこれで先に進めます。
    ありがとうございました!!

Your answer might help someone💌