クイックスタート
チュートリアル
ツールと言語
リファレンス
書評
正規表現チュートリアル
はじめに
目次
特殊文字
非表示文字
正規表現エンジンの内部
文字クラス
文字クラスの減算
文字クラスの積集合
文字クラスの省略形
ドット
アンカー
単語境界
オルタネーション
オプション項目
繰り返し
グループ化とキャプチャ
バックリファレンス
バックリファレンス、パート2
名前付きグループ
相対バックリファレンス
ブランチリセットグループ
フリースペースとコメント
Unicode
モード修飾子
アトミックグループ化
所有格量子化子
先行参照と後行参照
先行参照と後行参照、パート2
マッチからテキストを除外する
条件式
バランスグループ
再帰
サブルーチンプログラム
無限再帰
再帰と量子化子
再帰とキャプチャ
再帰とバックリファレンス
再帰とバックトラッキング
POSIXブラケット式
ゼロ長マッチ
マッチの継続
このサイトについて、その他
はじめに
正規表現クイックスタート
正規表現チュートリアル
置換文字列チュートリアル
アプリケーションと言語
正規表現の例
正規表現リファレンス
置換文字列リファレンス
書評
印刷可能なPDF
このサイトについて
RSSフィードとブログ
RegexBuddy—Better than a regular expression tutorial!

失敗したグループへのバックリファレンス

バックリファレンスに関する前のトピックは、バックリファレンスをまったくサポートしていない少数のフレーバーを除く、すべての正規表現フレーバーに適用されます。「前のキャプチャグループによってマッチしたテキストにマッチする」という説明に当てはまらないことを始めると、フレーバーの動作は異なります。

何もマッチしなかったキャプチャグループへのバックリファレンスと、マッチにまったく参加しなかったキャプチャグループへのバックリファレンスには違いがあります。正規表現(q?)b\1b. q?はオプションであり、何もマッチせず、(q?)が正常にマッチし、何もキャプチャしません。bbそして\1は、グループによってキャプチャされた何もないものに正常にマッチします。

ほとんどのフレーバーでは、正規表現(q)?b\1b. (q)にまったくマッチしないため、グループは何もキャプチャしません。グループ全体がオプションであるため、エンジンはbにマッチします。エンジンは次に\1に到達します。これは、マッチ試行にまったく参加しなかったグループを参照しています。これにより、バックリファレンスはまったくマッチしなくなり、グループの結果を模倣します。が存在しないため?\1をオプションにするため、全体的なマッチ試行は失敗します。

少数の例外の1つはJavaScriptです。公式のECMA標準によると、非参加のキャプチャグループへのバックリファレンスは、参加しているグループで何もキャプチャしなかったバックリファレンスと同様に、正常に何もマッチする必要があります。つまり、JavaScriptでは、(q?)b\1そして(q)?b\1の両方がbにマッチします。XPathも同様に動作します。

Dinkumwareのstd::regexの実装は、バックリファレンスをサポートするすべての構文について、JavaScriptのようにバックリファレンスを処理します。Boostもバージョン1.46まではそうでした。バージョン1.47以降、BoostはECMAScript構文を使用する場合、非参加グループへのバックリファレンスに失敗しますが、basicおよびgrep構文を使用する場合は、引き続き正常に何もマッチさせます。

存在しないキャプチャグループへのバックリファレンス

存在しないグループへのバックリファレンス(例:(one)\7)は、ほとんどの正規表現フレーバーではエラーです。ただし、例外があります。JavaScript\1\7として扱います。8進エスケープは、正規表現内のキャプチャグループがバックスラッシュの後の数字よりも少ない場合にのみ使用できます。\8そして\9はエラーです。8と9は有効な8進数ではないためです。

Javaは、存在しないグループへのバックリファレンスを、存在するがマッチにまったく参加しないグループへのバックリファレンスとして扱います。エラーではありませんが、単に何もマッチしません。

.NETはもう少し複雑です。.NETは、1桁と2桁のバックリファレンスと、先頭のゼロがない2桁の8進エスケープをサポートしています。バックリファレンスは8進エスケープよりも優先されます。そのため\12は、キャプチャグループが12未満の正規表現では改行(8進数12 = 10進数10)です。キャプチャグループが12個以上ある正規表現では、12番目のグループへのバックリファレンスになります。.NETは1桁の8進エスケープをサポートしていません。そのため\7は、キャプチャグループが7未満の正規表現ではエラーです。

前方参照

JGsoft.NETJavaPerlPCREPHPDelphiRubyなど、多くの最新の正規表現フレーバーは前方参照を許可しています。これにより、正規表現の後に表示されるグループへのバックリファレンスを使用できます。前方参照は、繰り返しグループ内にある場合にのみ役立ちます。次に、正規表現エンジンがグループが既にマッチした後にバックリファレンスを評価する状況があります。グループを試行する前に、バックリファレンスは失敗したグループへのバックリファレンスのように失敗します。

前方参照がサポートされている場合、正規表現(\2two|(one))+にマッチします。文字列の先頭で、\2は失敗します。別のオルタネーションを試みると、oneは2番目のキャプチャグループによってマッチされ、その後、最初のグループによってマッチされます。最初のグループはその後繰り返されます。今回は、\2oneが2番目のグループによってキャプチャされます。twoは次にtwoにマッチします。最初のグループを2回繰り返すことで、正規表現は対象文字列全体にマッチしました。

JavaScriptは前方参照をサポートしませんが、エラーとして扱いません。JavaScriptでは、前方参照は常にゼロ長文字列を見つけます。これは非参加グループへのバックリファレンスがJavaScriptで行うのと同じです。これは特に役立つものではないため、XRegExpではエラーになります。std::regexBoostPythonTclVBScriptでは、前方参照はエラーです。

ネストされた参照

ネストされた参照とは、参照するキャプチャグループ内のバックリファレンスです。前方参照と同様に、ネストされた参照は、以下のように繰り返しグループ内にある場合にのみ役立ちます。(\1two|(one))+ネストされた参照がサポートされている場合、この正規表現はにマッチします。文字列の先頭で、\1は失敗します。別のオルタネーションを試みると、oneは2番目のキャプチャグループによってマッチされ、その後、最初のグループによってマッチされます。最初のグループはその後繰り返されます。今回は、\1oneにもマッチします。これは、最初のグループの最後の反復によってキャプチャされます。正規表現エンジンが最初のグループに再入力をしたかどうかは問題ではありません。グループによってマッチしたテキストは、グループが以前に終了したときにバックリファレンスに格納されました。twoは次にtwo最初のグループを2回繰り返すことで、正規表現は対象文字列全体にマッチしました。マッチ後にキャプチャグループからテキストを取得する場合、最初のグループはonetwoを格納し、2番目のグループは文字列の最初の出現であるoneをキャプチャします。

JGsoft.NETJavaPerlVBScriptのフレーバーはすべて、ネストされた参照をサポートしています。PCREもサポートしていますが、ネストされたバックリファレンスを持つキャプチャグループへのバックトラッキングにバグがありました。バグを修正する代わりに、PCRE 8.01は、ネストされた参照を持つキャプチャグループをアトミックにすることで回避しました。そのため、PCREでは、(\1two|(one))+(?>(\1two|(one)))+と同じです。これは、PHPDelphiRなど、PCREをベースとした正規表現エンジンを持つ言語に影響します。

JavaScriptRubyはネストされた参照をサポートしませんが、エラーではなく、非参加グループへのバックリファレンスとして扱います。JavaScriptでは、これは常にゼロ長の文字列にマッチすることを意味し、Rubyでは常にマッチに失敗することを意味します。std::regexBoostPythonTclでは、ネストされた参照はエラーです。