以下の内容はhttps://lunastera.hatenablog.com/entry/2025/09/09/100940より取得しました。


正規表現の \1 と (?1) は違う

なんかあんまりここの違い解説している日本語記事無い気がするな〜と思ったので。

まず大前提としてどちらもキャプチャグループと一緒に使用されるもので、キャプチャグループがあった時にそれを正規表現内で再参照するというような仕組みです。ただその参照の仕方が \1 系と (?1) 系で違うよという話です。

\1 系はバックリファレンス(backreferences)と呼ばれていて、指定したキャプチャグループと同じ"文字列"にマッチします。 例えば (.)\1aa にはマッチするけど、 ab にはマッチしないよ、という構文。

一方で (?1) 系は再帰的サブパターン(recursive subpatterns)と呼ばれていて*1、指定したキャプチャグループと同じ"パターン"にマッチします。つまるところ (.)(?1) の場合、キャプチャグループ内の同じパターンを参照しているので aa にも ab にもマッチしてくれるよという代物です。

これを見ると基本的には再帰的サブパターンを使えばよさそうに見えてしまうのですが、これにも色々落とし穴はあって、たとえば <a><span>text</span></a> みたいな同名タグの入れ子を検証したいときに、うっかり /(?<NODE>(?&NODE)|<(?<TAG>[A-Za-z][A-Za-z0-9-]*)>(?:[^<]+|(?&NODE))*<\/\k<TAG>>)/x のように左再帰にしてしまうと入力を消費せず自己再帰することになり無限再帰に陥ってしまったりしますし、そもそも再帰的サブパターンは JavaScript などには無い*2ので移植する際などには注意が必要だったりします。

*1:PHPドキュメントだとそう書かれている: PHP: Subpatterns - Manual

*2:バックリファレンスはある: Backreference: \1, \2 - JavaScript | MDN




以上の内容はhttps://lunastera.hatenablog.com/entry/2025/09/09/100940より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14