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

アトミックグループ

アトミックグループとは、正規表現エンジンがグループから抜けるときに、グループ内のトークンによって記憶されているすべてのバックトラッキング位置を自動的に破棄するグループです。アトミックグループはキャプチャしません。構文は次のとおりです。(?>グループ)先読み/後読みグループもアトミックです。アトミックグループは、JGsoftフレーバー、JavaPCRE.NETPerlBoostRubyなど、最新の正規表現フレーバーのほとんどでサポートされています。これらのほとんどは、所有量指定子もサポートしており、これは基本的にアトミックグループの表記上の便宜です。Pythonは、Pythonバージョン3.11以降でアトミックグループと所有量指定子をサポートしています。

例を挙げると、アトミックグループの動作が明確になります。正規表現a(bc|b)c(キャプチャグループ)は、abccabcに一致します。正規表現a(?>bc|b)c(アトミックグループ)は、abccに一致しますが、abcには一致しません。abccabccabc.

abcabcabccaa, bcbcに一致し、その後、cは文字列の末尾で一致に失敗します。ここで、それらのパスは分岐します。キャプチャグループを持つ正規表現は、選択のバックトラッキング位置を記憶しています。グループは一致を放棄し、bbcbcに一致し、

cbcbccに一致しま す。一致が見つかりました!

ただし、アトミックグループを持つ正規表現は、bcが一致した後にアトミックグループから抜けました。その時点で、グループ内のトークンのすべてのバックトラッキング位置は破棄されます。この例では、文字列の2番目の位置でbを試すという選択肢は破棄されます。その結果、cが失敗すると、正規表現エンジンには試す選択肢がなくなります。

もちろん、上記の例はあまり役に立ちません。しかし、アトミックグループが特定の一致をどのように排除するかを明確に示しています。あるいは、より重要なのは、特定の一致の試みを排除することです。

アトミックグループを使用した正規表現の最適化正規表現\b(integer|insert|in)\bと対象文字列integers

を考えてみましょう。単語境界のため、これらは明らかに一致しません。それほど明白ではないのは、正規表現エンジンがこれを理解するためにかなりの労力を費やすことです。\bは文字列の先頭で一致し、integerはintegersの先頭の6文字と一致します。正規表現エンジンは、グループ内にさらに2つの選択肢があることに注意し、\bで続行します。これは、rとsの間では一致に失敗します。そのため、エンジンはバックトラックして、グループ内の2番目の選択肢を試します。2番目の選択肢はinsertの先頭の2文字であるinと一致しますが、その後、\bとの一致に失敗します。そのため、エンジンはもう一度バックトラックして、3番目の選択肢を試します。 \bは今回はnとtの間で失敗します。正規表現エンジンには記憶されているバックトラッキング位置がなくなったため、失敗を宣言します。bは文字列の先頭で一致し、integerはintegersの先頭の6文字と一致します。正規表現エンジンは、グループ内にさらに2つの選択肢があることに注意し、\bで続行します。これは、rとsの間では一致に失敗します。そのため、エンジンはバックトラックして、グループ内の2番目の選択肢を試します。2番目の選択肢はinsertの先頭の2文字であるinと一致しますが、その後、\bとの一致に失敗します。そのため、エンジンはもう一度バックトラックして、3番目の選択肢を試します。 \bは今回はnとtの間で失敗します。正規表現エンジンには記憶されているバックトラッキング位置がなくなったため、失敗を宣言します。integerを考えてみましょう。単語境界のため、これらは明らかに一致しません。それほど明白ではないのは、正規表現エンジンがこれを理解するためにかなりの労力を費やすことです。\brsin\b\binbin. を考えてみましょう。単語境界のため、これらは明らかに一致しません。それほど明白ではないのは、正規表現エンジンがこれを理解するためにかなりの労力を費やすことです。ntintegers

integerと対象文字列\bを考えてみましょう。単語境界のため、これらは明らかに一致しません。それほど明白ではないのは、正規表現エンジンがこれを理解するためにかなりの労力を費やすことです。integerは文字列の先頭で一致し、integerはintegersの先頭の6文字と一致します。正規表現エンジンは、グループ内にさらに2つの選択肢があることに注意し、\bで続行します。これは、rとsの間では一致に失敗します。そのため、エンジンはバックトラックして、グループ内の2番目の選択肢を試します。2番目の選択肢はinsertの先頭の2文字であるinと一致しますが、その後、\bとの一致に失敗します。そのため、エンジンはもう一度バックトラックして、3番目の選択肢を試します。 \bは今回はnとtの間で失敗します。正規表現エンジンには記憶されているバックトラッキング位置がなくなったため、失敗を宣言します。\b

キャプチャグループをアトミックグループ\b(?>integer|insert|in)\bに変換することで、これを行うことができます。integerが一致すると、エンジンはアトミックグループから抜け、選択のために保存したバックトラッキング位置を破棄します。\bが失敗すると、エンジンはすぐに諦めます。この節約は、キーワードの長いリストのために大きなファイルをスキャンする場合に重要になります。この節約は、選択肢にカタストロフィックバックトラッキングにつながる繰り返しトークン(繰り返しグループは言うまでもありません)が含まれている場合に不可欠です。は文字列の先頭で一致し、integerはintegersの先頭の6文字と一致します。正規表現エンジンは、グループ内にさらに2つの選択肢があることに注意し、\bで続行します。これは、rとsの間では一致に失敗します。そのため、エンジンはバックトラックして、グループ内の2番目の選択肢を試します。2番目の選択肢はinsertの先頭の2文字であるinと一致しますが、その後、\bとの一致に失敗します。そのため、エンジンはもう一度バックトラックして、3番目の選択肢を試します。 \bは今回はnとtの間で失敗します。正規表現エンジンには記憶されているバックトラッキング位置がなくなったため、失敗を宣言します。\bを考えてみましょう。単語境界のため、これらは明らかに一致しません。それほど明白ではないのは、正規表現エンジンがこれを理解するためにかなりの労力を費やすことです。\b

すべてのグループをアトミックにするのは早計です。上記の最初の例で見たように、アトミックグループ化は有効な一致も除外する可能性があります。\b(?>integer|insert|in)\b\b(?>in|integer|insert)\binsertに適用されたときの動作を比較してください。前者の正規表現は一致しますが、後者は一致しません。グループがアトミックでなかった場合、両方の正規表現は一致します。選択は選択肢を左から右に試行することに注意してください。2番目の正規表現がinと一致する場合、アトミックグループのため、他の2つの選択肢は試行されません。inin