【質問】正規表現での名前付き部分式の仕No.39562
でるもんたいいじま さん 22/02/09 00:10
 
でるもんた・いいじまです。

さきほど4番会議室に投稿させていただいたご提案に関して少し実験してみたのです
が、仕様なのかたまたま今の実装がそうなっているだけなのか判断つきかねているの
で、質問させてください。

まず、エディタに
  xyxyxyxy
の8文字を入力します。

次に検索ダイアログを開いて、下記の正規表現で検索をかけます。
  (?<a>x)(?<a>y)\g<a>\g<a>
そうするとヒットしません。

次に\g<a>を一つ削って
  (?<a>x)(?<a>y)\g<a>
とすると、先頭の「xyx」と5文字目からの「xyx」がヒットします。

最終的に
  (?<a>x)(?<a>y).\g<a>
としてみると、案の定、ヒットしません。

というわけで、(?<名前>パターン) というパターンは現状、次のような実装になって
いることが分かりますが、これを「正式な仕様」と考えても大丈夫でしょうか?

@同じ「名前」と別々の「パターン」の組み合わせを複数回書いてもエラーにはなら
ず、その場ではすんなり「パターン」にヒットする。今回の例でいえば (?<a>y) は
ちゃんと y にヒットする。
Aところがそういう場合でも、\g<パターン> は最初に定義したときのパターンにマ
ッチする。今回は一番最初に (?<a>x) があるので、そのあと (?<a>…) として何が
来ても \g<a> は x のままであって、後から再定義しても上書きされない。

ちなみに他の実装の例だと、
https://perldoc.jp/docs/perl/5.26.1/perlre.pod
あたりでは「最初の定義が有効」と明言しています。

“数値を全く使わずに、名前付き捕捉グループを作ることが出来ます。記法は、宣言
が (?<name>...)、参照が \g{name} です。 (中略)同じパターンの中に同じ名前の
違うグループがある場合、この名前での参照は一番左で定義されたものを仮定します。


以上、よろしくお願いいたします。

[ ]
RE:39562 【質問】正規表現での名前付き部No.39563
秀まるお2 さん 22/02/09 09:39
 
 部分式を同じ名前で複数定義するケースは想定してなくて、テストもしたことがあ
りませんでした。

 テストしてみたら、たしかに先に見つかる方が有効になるようです。たまたまそう
なってしまってるというだけで、そういう仕様を保証してる訳ではないです。

> ちなみに他の実装の例だと、
> https://perldoc.jp/docs/perl/5.26.1/perlre.pod
> あたりでは「最初の定義が有効」と明言しています。

 HmJre.dllでも現状そういう仕様になってるとは思うんですが、そこまで保証でき
るほどテストした訳でも無いので、今のところは不確定だと思ってもらいたい所です。

[ ]
RE:39563 【質問】正規表現での名前付き部No.39564
でるもんたいいじま さん 22/02/09 20:28
 
でるもんた・いいじまです。お返事ありがとうございます。

> > ちなみに他の実装の例だと、
> > https://perldoc.jp/docs/perl/5.26.1/perlre.pod
> > あたりでは「最初の定義が有効」と明言しています。
>
> HmJre.dllでも現状そういう仕様になってるとは思うんですが、
> そこまで保証できるほどテストした訳でも無いので、
> 今のところは不確定だと思ってもらいたい所です。

了解しました。
実装を想像するに、部分式の「名前→中身」の対照表は単純な配列か何かになってい
て、部分式定義を見つけたら末尾に追加する、部分式参照を見つけたら先頭からサー
チして最初のヒットを採用する、という設計ですかね。だとすると確かに、この対照
表の実装が変わるだけで結果が変わってしまいます。

とりあえず他のメジャーな実装がどうなっているのか、調べてみようと思います。
(上記でPerlのドキュメントを引用していますが、hmjre.chmによればRuby由来との
ことですし、Perlのドキュメントのほうには「(Perlの最新版では).NETとの互換性の
ため\gの代わりに\kも使用可能」「PythonやPCREの(?P=名前)も使用可能」とありま
す。)

[ ]