このサイトについて |
はじめに |
正規表現クイックスタート |
正規表現チュートリアル |
置換文字列チュートリアル |
アプリケーションと言語 |
正規表現の例 |
正規表現リファレンス |
置換文字列リファレンス |
書籍レビュー |
印刷可能なPDF |
このサイトについて |
RSSフィードとブログ |
Perl 5.10、PCRE 4.0、Ruby 2.0、およびこれら3つの後続のすべてのバージョンは、正規表現の再帰をサポートしています。Perlは構文(?R)を(?0)の同義語として使用します。Ruby 2.0は\g<0>を使用します。PCREはバージョン7.7から3つすべてをサポートしています。以前のバージョンでは、Perlの構文のみをサポートしていました(Perlは実際にはPCREからコピーしました)。Delphi、PHP、およびRの最近のバージョンも、正規表現関数がPCREに基づいているため、3つすべてをサポートしています。JGsoft V2も正規表現の再帰のすべてのバリエーションをサポートしています。
Ruby 1.9は正規表現の再帰の構文を持っていませんが、キャプチャグループの再帰をサポートしています。したがって、正規表現全体をキャプチャグループでラップすると、Ruby 1.9で正規表現全体を再帰させることができます。.NETは再帰をサポートしていませんが、バランシンググループをサポートしており、再帰の代わりにこれを使用してバランスの取れた構造をマッチさせることができます。
後で説明するように、Perl、PCRE、およびRubyが、再帰中の後方参照とバックトラッキングをどのように処理するかには違いがあります。それらは互いの構文をコピーしましたが、互いの動作はコピーしませんでした。しかし、JGsoft V2はそれらの構文と動作をコピーしました。したがって、JGsoft V2には、異なる構文を使用することで選択できる、正規表現の再帰を行う3つの異なる方法があります。ただし、これらの違いは、このページの基本的な例では問題になりません。
Boost 1.42はPerlから構文をコピーしました。しかし、その実装はバグによって損なわれています。Boost 1.60は再帰における量指定子の動作を修正しようとしましたが、他のフレーバーとは大きく異なり、以前のバージョンのBoostとは互換性がありません。Boost 1.64では、無限再帰でクラッシュするのを最終的に停止しました。しかし、正規表現全体の再帰は、最初の選択肢のみを試みます。
正規表現a(?R)?z, a(?0)?z、およびa\g<0>?zは、1つ以上の文字aの後に、まったく同じ数の文字zが続くものすべてにマッチします。これらの正規表現は機能的に同一であるため、この正規表現が文字列aaazzz.
にどのようにマッチするかを確認するために、再帰にRを使用する構文を使用します。aまず、aは文字列の最初の(?R)にマッチします。次に、正規表現エンジンはaに到達します。これにより、エンジンは文字列の現在の位置で正規表現全体をもう一度試みるように指示されます。さて、aは文字列の2番目の(?R)にマッチします。エンジンは再びaに到達します。2回目の再帰では、aは3番目のaにマッチします。3回目の再帰では、zは文字列の最初の(?R)にマッチしません。これにより、(?R) は失敗します。ただし、正規表現では量指定子を使用してzオプションにします。したがって、エンジンはzに進み、文字列の最初の
にマッチします。(?R)これで、正規表現エンジンは正規表現の終わりに到達しました。しかし、2レベルの再帰内にあるため、まだ全体的な一致は見つかっていません。見つかったのはzのみの一致です。一致が成功した後で再帰を終了すると、エンジンはzにも到達します。これで、文字列の2番目のzに到達します。2回目の再帰では、zにマッチします。エンジンはまだ再帰の1レベル深く、そこから一致が成功して終了します。最後に、aaazzzに到達します。エンジンは再び正規表現の終わりにあります。今回は再帰の中にはありません。したがって、全体的な正規表現の一致として
バランスの取れた構造のマッチング再帰の主な目的は、バランスの取れた構造またはネストされた構造にマッチすることです。一般的な正規表現はb(?:m|(?R))*eです。ここで、bは構造の開始となるもので、mは構造の中央で発生する可能性のあるもので、eです。ここで、, は構造の開始となるもので、、およびは構造の中央で発生する可能性のあるもので、は構造の終わりに発生する可能性のあるものです。正しい結果を得るには、のいずれも同じテキストにマッチすることができないようにする必要があります。非キャプチャグループの代わりにアトミックグループを使用すると、パフォーマンスが向上します。.
b(?>m|(?R))*e一般的な実際の使用例は、バランスの取れた一連の括弧をマッチさせることです。\((?>[^()]|(?R))*\)
選択による再帰バランスの取れた構造の中央に表示されるものが、開始部分と終了部分なしで単独で表示される可能性もある場合、一般的な正規表現はb(?R)*e|mです。ここで、, は構造の開始となるもので、、およびは構造の中央で発生する可能性のあるもので、です。ここでも、はすべて相互に排他的である必要があります。\((?R)*\)|[^()]+
は、前のセクションの正規表現のように、バランスの取れた括弧のペアにマッチします。ただし、括弧をまったく含まないテキストにもマッチします。はすべて相互に排他的である必要があります。この正規表現は、Boostでは正しく機能しません。正規表現にグループ内にない選択がある場合、Boostでの正規表現全体の再帰は、最初の選択肢のみを試みます。したがって、は、間にテキストがない、任意に深くネストされたバランスの取れた括弧の数、または括弧をまったく含まないテキストにマッチします。選択肢を反転すると、[^()]+|\((?R)*\)
は、Boostでは、括弧を含まないテキスト、または括弧を含まないテキストで囲まれた括弧の単一のペアにマッチします。他のすべてのフレーバーでは、これらの2つの正規表現は同じマッチを見つけます。Boostの解決策は、選択をグループ内に入れることです。(?:\((?R)*\)|[^()]+)および(?:[^()]+|\((?R)*\))
は、再帰をサポートするこのチュートリアルで説明したすべてのフレーバーで同じマッチを見つけます。
| はじめに | 目次 | 特殊文字 | 非印字文字 | 正規表現エンジンの内部構造 | 文字クラス | 文字クラスの減算 | 文字クラスの交差 | 省略形の文字クラス | ドット | アンカー | 単語境界 | 選択 | オプション項目 | 繰り返し | グループ化とキャプチャ | 後方参照 | 後方参照、パート2 | 名前付きグループ | 相対後方参照 | ブランチリセットグループ | 自由な空白とコメント | Unicode | モード修飾子 | アトミックグループ | 強欲な量指定子 | 先読みと後読み | 先読みと後読み、パート2 | マッチからテキストを除外 | 条件 | バランシンググループ | 再帰 | サブルーチン | 無限再帰 | 再帰と量指定子 | 再帰とキャプチャ | 再帰と後方参照 | 再帰とバックトラック | POSIXブラケット式 | ゼロ長の照合 | マッチの継続 |
ページ URL: https://regular-expressions.dokyumento.jp/recurse.html
最終更新日: 2019年11月22日
サイト最終更新日: 2024年3月15日
Copyright © 2003-2024 Jan Goyvaerts. All rights reserved.