このサイトのその他の情報 |
はじめに |
正規表現クイックスタート |
正規表現チュートリアル |
置換文字列チュートリアル |
アプリケーションとプログラミング言語 |
正規表現の例 |
正規表現リファレンス |
置換文字列リファレンス |
書評 |
印刷可能なPDF |
このサイトについて |
RSSフィード & ブログ |
特別な構文(?ifthen|else)を使用すると、条件付き正規表現を作成できます。if 部分が真と評価された場合、正規表現エンジンは then 部分のマッチを試みます。それ以外の場合は、代わりに else 部分が試行されます。構文は、一対の括弧で構成されています。開始括弧の直後に疑問符が続き、直後に if 部分、直後に then 部分が続きます。この部分には、縦棒と else 部分を続けることができます。else 部分と縦棒は省略できます。
if 部分には、先読みと後読み構文を使用できます。肯定先読みを使用すると、構文は次のようになります。(?(?=正規表現)then|else)。先読みには独自の括弧があるため、if 部分と then 部分は明確に区切られています。
先読み/後読み構文は文字を消費しないことを覚えておいてください。if 部分として先読みを使用すると、正規表現エンジンは、(先読みの結果に応じて)then 部分または else 部分を、if が試行されたのと同じ位置でマッチさせようとします。
あるいは、if 部分でキャプチャグループがこれまでのマッチに関与しているかどうかを確認することもできます。キャプチャグループの番号を括弧内に入れ、それを if 部分として使用します。後方参照の条件付きチェックの構文は、キャプチャグループ内の数字と同じですが、キャプチャグループは作成されないことに注意してください。番号と括弧は、で始まるif-then-else構文の一部です(?.
then と else には、任意の正規表現を使用できます。選択を使用する場合は、次のように、括弧を使用してthen または else をグループ化する必要があります。(?(?=条件)(then1|then2|then3)|(else1|else2|else3))。そうでない場合は、then 部分と else 部分を括弧で囲む必要はありません。
正規表現(a)?b(?(1)c|d)はオプションのキャプチャグループで構成されています(a)?、リテラルb、および条件式(?(1)c|d)がキャプチャグループをテストします。この正規表現はbdとabcに一致します。これはbcには一致しませんが、bdinabdには一致します。この正規表現がこれら4つの対象文字列それぞれに対してどのように機能するかを見てみましょう。
が適用されるとbd, aのマッチに失敗します。を含むキャプチャグループはaがオプションであるため、エンジンはb対象文字列の先頭で続行します。グループ全体がオプションであるため、グループはマッチに関与しませんでした。その後の後方参照は\1は失敗します。であることに注意してください(a)?は(a?)とは大きく異なります。前者の正規表現では、キャプチャグループはaが失敗した場合、マッチに関与せず、そのグループへの後方参照は失敗します。後者のグループでは、キャプチャグループは常にマッチに関与し、aまたは何もキャプチャしません。マッチに参加して何もキャプチャしなかったキャプチャグループへの後方参照は常に成功します。このようなグループを評価する条件式は、「then」部分を実行します。要するに、条件式でグループへの参照を使用する場合は、(a)?の代わりに(a?).
を使用してください。正規表現を続行すると、bはbに一致します。正規表現エンジンはここで条件式を評価します。最初のキャプチャグループはマッチにまったく参加しなかったため、「else」部分またはdが試行されます。dはd全体的なマッチが見つかります。
2番目の対象文字列abc, aはaに進みます。これは、キャプチャグループによってキャプチャされます。続いて、bはbです。正規表現エンジンは、再度条件式を評価します。キャプチャグループはマッチに参加したので、「then」部分またはcが試行されます。cはc全体的なマッチが見つかります。
が試行されます。3番目の対象bcはaで始まらないため、最初の対象文字列で見たように、キャプチャグループはマッチの試行に参加しません。bは依然としてbに一致し、エンジンは条件式に進みます。最初のキャプチャグループはマッチにまったく参加しなかったため、「else」部分またはdが試行されます。dはcに一致せず、文字列の先頭でのマッチ試行は失敗します。エンジンは文字列の2番目の文字からもう一度試行しますが、bはc.
のため失敗します。4番目の対象abdが最も興味深いものです。2番目の文字列と同様に、キャプチャグループはaを取得し、bに一致します。キャプチャグループはマッチに参加したので、「then」部分またはcが試行されます。cはdに一致せず、マッチ試行は失敗します。この時点では「else」部分は試行されないことに注意してください。キャプチャグループはマッチに参加したので、「then」部分のみが使用されます。ただし、正規表現エンジンはまだ完了していません。正規表現を最初から再起動し、対象文字列の文字を1つ進めます。
文字列の2番目の文字から開始すると、aはbとなります。キャプチャグループは、文字列の2番目の文字から開始された2番目のマッチ試行には参加しません。正規表現エンジンはオプションのグループを超えて進み、bを試行します。これは一致します。正規表現エンジンは正規表現の条件式に到達し、対象文字列の3番目の文字に到達します。最初のキャプチャグループは現在のマッチ試行に参加しなかったので、「else」部分またはdが試行されます。dはdとなり、全体的なマッチbdが見つかります。
この最後のマッチ結果を回避するには、アンカーを使用する必要があります。^(a)?b(?(1)c|d)$は、最後の対象文字列に一致するものを見つけられません。キャレットは、文字列の2番目と3番目の文字の前で一致に失敗します。
条件式は、JGsoftエンジン、Perl、PCRE、Python、および.NETでサポートされています。Rubyは、バージョン2.0以降でそれらをサポートしています。Delphi、PHP、およびPCREに基づく正規表現機能を持つRなどの言語も条件式をサポートしています。
これらのフレーバーはすべて、名前付きキャプチャグループもサポートしています。if テストとして、キャプチャグループの番号の代わりに名前を使用できます。構文は正規表現のフレーバー間でわずかに異なります。Python、.NET、およびJGsoftアプリケーションでは、括弧の間にグループの名前を指定するだけです。(?<test>a)?b(?(test)c|d)は、名前付きキャプチャを使用した前のセクションの正規表現です。PerlまたはRubyでは、グループの名前を山括弧または引用符で囲み、それを条件式の括弧の間に置く必要があります。(?<test>a)?b(?(<test>)c|d)または(?'test'a)?b(?('test')c|d)。PCREは3つのバリアントすべてをサポートしています。
PCRE 7.2以降およびJGsoft V2も、相対条件式をサポートしています。構文は、グループ番号の前にプラスまたはマイナス記号が追加された、番号付きキャプチャグループを参照する条件式の構文と同じです。条件式は、次に、(?(条件式を開くものから、左(マイナス)または右(プラス)の開始括弧を数えます。(a)?b(?(-1)c|d)は、上記の正規表現を記述する別の方法です。利点は、正規表現の先頭または末尾にキャプチャグループを追加しても、この正規表現が壊れないことです。
Pythonは、番号付きまたは名前付きのキャプチャグループを使用した条件式をサポートしています。Pythonは、条件式の外で先読みをサポートしている場合でも、先読みを使用した条件式をサポートしていません。次のような条件式の代わりに(?(?=正規表現)then|else)、2つの反対の先読みを交互に適用できます(?=正規表現)then|(?!正規表現)else.
BoostとRubyでは、存在しないキャプチャグループを参照する条件式をエラーとして扱います。このチュートリアルで取り上げている他のフレーバーの最新バージョンでは、そうではありません。そのような条件式は常に「else」の部分を試行するだけです。ただし、いくつかのフレーバーでは考えが変わりました。Python 3.4以前とPCRE 7.6以前(したがってPHP 5.2.5以前)では、以前はエラーとして扱っていました。
正規表現^((From|To)|Subject): ((?(2)\w+@\w+\.[a-z]+|.+))は、メールメッセージからFrom、To、Subjectヘッダーを抽出します。ヘッダーの名前は、最初の後方参照にキャプチャされます。ヘッダーがFromまたはToヘッダーの場合、2番目の後方参照にもキャプチャされます。
パターンの2番目の部分は、if-then-else条件です(?(2)\w+@\w+\.[a-z]+|.+))。「if」部分は、これまでのマッチで2番目のキャプチャグループが参加したかどうかをチェックします。ヘッダーがFromまたはToヘッダーの場合、参加したことになります。その場合、条件式の「then」部分\w+@\w+\.[a-z]+は、メールアドレスをマッチさせようとします。例を簡単にするために、メールアドレスをマッチさせるために非常に単純な正規表現を使用しており、通常FromまたはToヘッダーの一部である表示名もマッチさせようとはしていません。
2番目のキャプチャグループがこれまでのマッチに参加しなかった場合、「else」部分.+が代わりに試行されます。これは、テスト対象を問わず、行の残りの部分を単にマッチさせます。
最後に、条件式の周りに追加の括弧のペアを配置します。これにより、条件式によってマッチしたメールヘッダーの内容が3番目の後方参照にキャプチャされます。条件式自体は何もキャプチャしません。この正規表現を実装すると、最初のキャプチャグループはヘッダーの名前(「From」、「To」、または「Subject」)を格納し、3番目のキャプチャグループはヘッダーの値を格納します。
「else」部分に別の条件式を入れることで、さらに多くのヘッダーをマッチさせることができます。例:^((From|To)|(Date)|Subject): ((?(2)\w+@\w+\.[a-z]+|(?(3)mm/dd/yyyy|.+)))は、「From」、「To」、「Date」、または「Subject」をマッチさせ、「regex」を使用しますmm/dd/yyyyで、日付が有効かどうかをチェックします。明らかに、日付の検証regexは、例を簡単にするためのダミーです。ヘッダーは最初のグループにキャプチャされ、検証済みの内容は4番目のグループにキャプチャされます。
ご覧のとおり、条件式を使用する正規表現はすぐに扱いにくくなります。1つの正規表現しか使用できないツールの場合にのみ使用することをお勧めします。プログラミングでは、正規表現を使用する方がはるかに優れています^(From|To|Date|Subject): (.+)は、検証されていない内容を含む1つのヘッダーをキャプチャします。ソースコードで、最初のキャプチャグループで返されたヘッダーの名前を確認し、次に2番目の正規表現を使用して、最初の正規表現の2番目のキャプチャグループで返されたヘッダーの内容を検証します。いくつかの行の追加コードを記述する必要があるでしょうが、このコードははるかに理解しやすく、保守しやすくなります。すべての正規表現をプリコンパイルする場合、複数の正規表現を使用することは、条件式でいっぱいの1つの大きな正規表現よりも、高速ではないにしても、同じくらい高速になります。
| クイックスタート | チュートリアル | ツールと言語 | 例 | リファレンス | 書籍レビュー |
| はじめに | 目次 | 特殊文字 | 印刷不可能な文字 | 正規表現エンジンの内部 | 文字クラス | 文字クラスの減算 | 文字クラスの共通部分 | 短縮文字クラス | ドット | アンカー | 単語境界 | 選択 | オプション項目 | 繰り返し | グループ化とキャプチャ | 後方参照 | 後方参照、パート2 | 名前付きグループ | 相対後方参照 | ブランチリセットグループ | 自由な間隔とコメント | Unicode | モード修飾子 | アトミックグループ化 | 所有量指定子 | 先読みと後読み | 先読み、パート2 | マッチからテキストを除外 | 条件式 | バランスグループ | 再帰 | サブルーチン | 無限再帰 | 再帰と量指定子 | 再帰とキャプチャ | 再帰と後方参照 | 再帰とバックトラック | POSIXブラケット式 | 長さゼロのマッチ | マッチの継続 |
ページURL:https://regular-expressions.dokyumento.jp/conditional.html
ページ最終更新日:2021年8月12日
サイト最終更新日:2024年3月15日
Copyright © 2003-2024 Jan Goyvaerts. All rights reserved.