このサイトの詳細 |
はじめに |
正規表現クイックスタート |
正規表現チュートリアル |
置換文字列チュートリアル |
アプリケーションと言語 |
正規表現の例 |
正規表現リファレンス |
置換文字列リファレンス |
書籍レビュー |
印刷可能なPDF |
このサイトについて |
RSSフィード & ブログ |
後方参照は、キャプチャグループによって以前にマッチしたテキストと同じテキストにマッチします。たとえば、開始と終了のHTMLタグのペアと、その間のテキストにマッチさせたいとします。開始タグを後方参照に入れることで、終了タグのタグ名を再利用できます。方法は次のとおりです。<([A-Z][A-Z0-9]*)\b[^>]*>.*?</\1>。この正規表現には、括弧のペアが1つだけ含まれており、これはによってマッチした文字列をキャプチャします。[A-Z][A-Z0-9]*。これが開始HTMLタグです。(HTMLタグは大文字と小文字を区別しないため、この正規表現では大文字と小文字を区別しないマッチングが必要です。)後方参照\1(バックスラッシュ1)は、最初のキャプチャグループを参照します。\1は、最初のキャプチャグループによってマッチしたテキストとまったく同じテキストにマッチします。それの前の/はリテラル文字です。これは、マッチさせようとしている終了HTMLタグのスラッシュです。
特定の後方参照の数を把握するには、正規表現を左から右にスキャンします。番号付きのキャプチャグループのすべての開始括弧を数えます。最初の括弧は後方参照番号1を開始し、2番目は番号2を開始します。非キャプチャグループなどの他の構文の一部である括弧はスキップします。これは、非キャプチャ括弧に別の利点があることを意味します。後方参照に割り当てられた番号を変更せずに正規表現に挿入できます。これは、複雑な正規表現を変更する場合に非常に役立ちます。
同じ後方参照を複数回再利用できます。([a-c])x\1x\1は、次のものにマッチします。axaxa, bxbxbそしてcxcxc.
ほとんどの正規表現フレーバーは、最大99個のキャプチャグループと2桁の後方参照をサポートしています。したがって\99は、正規表現に99個のキャプチャグループがある場合に有効な後方参照です。
正規表現エンジンが正規表現をどのように適用するかを見てみましょう。<([A-Z][A-Z0-9]*)\b[^>]*>.*?</\1>文字列Testing <B><I>bold italic</I></B> text。正規表現の最初のトークンはリテラルです<。正規表現エンジンは、文字列内の最初の<でマッチするまで文字列を走査します。次のトークンは[A-Z]。正規表現エンジンは、キャプチャ括弧の最初のペアの内側になったことにも注意します。[A-Z]は、次のものにマッチします。B。エンジンはに移動します。[A-Z0-9]そして>。このマッチングは失敗します。ただし、アスタリスクがあるため、問題ありません。文字列内の位置はのままです。>。単語境界\bはでマッチします。>これはの後に続くためです。B。単語境界では、エンジンは文字列を走査しません。正規表現内の位置はに進みます。[^>].
このステップでは、キャプチャ括弧の最初のペアの閉じ括弧を通過します。これにより、正規表現エンジンは、その中にマッチしたものを最初の後方参照に格納するように促されます。この場合、Bが格納されます。
後方参照を格納した後、エンジンはマッチングの試行を続けます。[^>]はマッチしません。>。繰り返しますが、別の星があるため、これは問題ではありません。文字列内の位置はのままです。>、正規表現内の位置はに進みます。>。これらは明らかにマッチします。次のトークンはドットで、怠惰なアスタリスクによって繰り返されます。怠惰のため、正規表現エンジンはこのトークンを最初にスキップし、正規表現の残りの部分が失敗した場合にバックトラックする必要があることに注意します。
エンジンは正規表現の2番目の<に、文字列の2番目の<に到達しました。これらはマッチします。次のトークンは/です。これはマッチしません。I、エンジンはドットにバックトラックすることを余儀なくされます。ドットは2番目の<にマッチします。アスタリスクはまだ怠惰なので、エンジンは利用可能なバックトラッキング位置を再び記録し、に進みます。<そしてI。これらはマッチしないため、エンジンは再びバックトラックします。
ドットが<I>bold italicを消費するまで、バックトラッキングは続きます。この時点で、<は文字列の3番目の<にマッチし、次のトークンは/であり、これはにマッチします。/。次のトークンは\1です。トークンは後方参照であり、Bではありません。エンジンは正規表現の後方参照を代入しません。エンジンが後方参照に到達するたびに、格納された値を読み取ります。これは、エンジンが2回目の\1に到達する前に、キャプチャ括弧の最初のペアを超えてバックトラックした場合、最初の後方参照に格納された新しい値が使用されることを意味します。しかし、ここではそうならなかったので、Bそのとおりです。これはでマッチに失敗します。I、したがって、エンジンは再びバックトラックし、ドットは3番目の<を消費します。
ドットが<I>bold italic</I>を消費するまで、バックトラッキングは続きます。この時点で、<は、次のものにマッチします。<そして/は、次のものにマッチします。/を消費するまで、バックトラッキングは再び続きます。エンジンは再び\1に到達します。後方参照はまだB. \1は、次のものにマッチします。Bを保持しています。正規表現の最後のトークンである>は、次のものにマッチします。>。完全一致が見つかりました。<B><I>bold italic</I></B>.
上記の\bの単語境界について疑問に思われたかもしれません。<([A-Z][A-Z0-9]*)\b[^>]*>.*?</\1>これは、正規表現が次のような誤ってペアリングされたタグに誤ってマッチしないようにするためです。<boo>bold</b>。キャプチャグループがbooにマッチし、これにより\1は同じものにマッチしようとして失敗する可能性があると思われるかもしれません。実際、それは起こります。しかし、その後、正規表現エンジンはバックトラックします。
正規表現<([A-Z][A-Z0-9]*)[^>]*>.*?</\1>を単語境界なしで使用し、\1が最初に失敗する時点で正規表現エンジンの中を見てみましょう。まず、.*?は文字列の最後まで拡張し続け、</\1>は毎回マッチに失敗しています。.*?は1文字多くマッチしました。
次に、正規表現エンジンはキャプチャグループにバックトラックします。[A-Z0-9]*はマッチしましたoo、しかし同じようににマッチします。oまたは何もありません。バックトラックすると、[A-Z0-9]*は1文字を諦めることを余儀なくされます。正規表現エンジンは続行し、キャプチャグループを2回目に終了します。以来、[A-Z][A-Z0-9]*はマッチしましたbo、それはキャプチャグループに格納され、boo以前に格納されていたものを上書きします。[^>]*は、開始タグの2番目のoにマッチします。>.*?</は、次のものにマッチします。>bold</. \1は再び失敗します。
正規表現エンジンは、[A-Z0-9]*がさらに1文字を諦めることを余儀なくされ、アスタリスクが許可するマッチングをしないようにするまで、すべて同じバックトラッキングをもう一度行います。キャプチャグループは現在、b. [^>]*のみを格納しています。今ではマッチしますoo. >.*?</は再びマッチします>bold<. \1は成功し、全体的なマッチングが見つかります。しかし、私たちが望んでいたものではありません。>これにはいくつかの解決策があります。1つは、単語境界を使用することです。
が最初にバックトラックし、キャプチャグループをに減らすとき、[A-Z0-9]*はに減らすbo, \bの間でマッチしません。oそしてo。これにより、[A-Z0-9]*はすぐに再びバックトラックすることを余儀なくされます。キャプチャグループはに減らされますbそして、単語境界はの間で失敗します。bそしてo。これ以上バックトラッキング位置がないため、マッチングの試行全体が失敗します。
単語境界が必要な理由は、タグ内の属性をスキップするために[^>]*を使用しているためです。ペアになったタグに属性がない場合は、それを省略して、<([A-Z][A-Z0-9]*)>.*?</\1>を使用できます。毎回[A-Z0-9]*はバックトラックし、>それに続くものが一致しない場合、マッチ試行はすぐに終了します。
正規表現エンジンがキャプチャグループにバックトラックすることを望まない場合は、アトミックグループを使用できます。「アトミックグループ化」のチュートリアルセクションに詳細がすべて記載されています。
上記の内側からの観察で述べたように、正規表現エンジンは正規表現内の後方参照を永続的に置換しません。後方参照を使用する必要があるたびに、最後に保存された一致を使用します。キャプチャ括弧によって新しい一致が見つかった場合、以前に保存された一致は上書きされます。明確な違いがあります。([abc]+)そして([abc])+。どちらも正常に一致しますがcab、最初の正規表現はcabを最初の後方参照に入れますが、2番目の正規表現はbのみを保存します。それは、2番目の正規表現では、プラス記号によって括弧のペアが3回繰り返されたためです。最初,cが保存されました。2回目,a、そして3回目b。毎回、前の値が上書きされたため、bが残ります。
これはまた、([abc]+)=\1がcab=cabと一致し、([abc])+=\1は一致しないことを意味します。その理由は、エンジンが\1に到達したとき、bを保持しており、それがcと一致しないためです。このような単純な例を見れば明らかですが、それでも正規表現でよくある困難の原因です。後方参照を使用する場合は、本当に必要なものをキャプチャしているかどうかを常に再確認してください。
テキストを編集するとき、「the the」のような重複した単語が簡単に紛れ込みます。正規表現\b(\w+)\s+\1\bをテキストエディターで使用すると、簡単に見つけることができます。2番目の単語を削除するには、単純に\1を置換テキストとして入力し、[置換]ボタンをクリックします。
括弧は文字クラス内では、少なくともメタ文字としては使用できません。文字クラスに括弧を入れると、リテラル文字として扱われます。したがって、正規表現[(a)b]は、次のものにマッチします。a, b, (、および).
後方参照も、文字クラス内では使用できません。次のような正規表現の\1(a)[\1b]はエラーであるか、または不必要にエスケープされたリテラル1です。JavaScriptでは、8進数エスケープです。
| クイックスタート | チュートリアル | ツールと言語 | 例 | リファレンス | 書籍レビュー |
| はじめに | 目次 | 特殊文字 | 非印刷文字 | 正規表現エンジンの内部 | 文字クラス | 文字クラスの減算 | 文字クラスの交差 | 短縮文字クラス | ドット | アンカー | 単語境界 | オルタネーション | オプション項目 | 繰り返し | グループ化とキャプチャ | 後方参照 | 後方参照、パート2 | 名前付きグループ | 相対後方参照 | ブランチリセットグループ | 自由間隔とコメント | Unicode | モード修飾子 | アトミックグループ化 | 所有数量詞 | 先読みと後読み | 先読みと後読み、パート2 | 一致からテキストを除外 | 条件付き | バランシンググループ | 再帰 | サブルーチン | 無限再帰 | 再帰と数量詞 | 再帰とキャプチャ | 再帰と後方参照 | 再帰とバックトラッキング | POSIXブラケット式 | ゼロ長の照合 | 照合の継続 |
ページURL: https://regular-expressions.dokyumento.jp/backref.html
最終更新日: 2021年8月12日
サイト最終更新日: 2024年3月15日
Copyright © 2003-2024 Jan Goyvaerts. All rights reserved.