正規表現の先読み、後読み、およびアトミックグループ


314

正規表現の本文でこれらの項目を見つけましたが、それらを何に使用できるのかわかりません。誰かが例を持っているので、それらがどのように機能するかを理解しようとすることができますか?

(?!) - negative lookahead
(?=) - positive lookahead
(?<=) - positive lookbehind
(?<!) - negative lookbehind

(?>) - atomic group

18
なぜ正規表現のウェブサイトにはこのような簡単な表がないのですか?代わりに、説明のみのテキストブロックがあります。regular-expressions.info/lookaround.html
Whitecat

3
@Whitecat Try:regex101.com regexr.com
Andrew

回答:


852

与えられた文字列foobarbarfoo

bar(?=bar)     finds the 1st bar ("bar" which has "bar" after it)
bar(?!bar)     finds the 2nd bar ("bar" which does not have "bar" after it)
(?<=foo)bar    finds the 1st bar ("bar" which has "foo" before it)
(?<!foo)bar    finds the 2nd bar ("bar" which does not have "foo" before it)

それらを組み合わせることもできます:

(?<=foo)bar(?=bar)    finds the 1st bar ("bar" with "foo" before it and "bar" after it)

定義

前向きに見て (?=)

式Bが続く式Aを見つけます。

A(?=B)

ネガティブな先読み (?!)

式Bが従わない式Aを見つけます。

A(?!B)

ポジティブの後ろを見る (?<=)

式Bが先行する式Aを見つけます。

(?<=B)A

ネガティブの後ろを見る (?<!)

式Bが先行しない式Aを検索します。

(?<!B)A

原子団 (?>)

アトミックグループはグループを終了し、グループ内で最初に一致したパターンの後に代替パターンを破棄します(バックトラッキングは無効です)。

  • (?>foo|foot)s適用先footsは最初の代替案fooに一致し、sすぐにフォローしないため失敗し、バックトラックが無効になると停止します

非原子グループはバックトラックを許可します。後続のマッチングが失敗した場合、式全体の一致が見つかるか、すべての可能性がなくなるまで、バックトラックして代替パターンを使用します。

  • (foo|foot)sfoots意志に適用:

    1. 1番目の選択肢fooに一致し、sすぐにフォローされないため失敗footsし、2番目の選択肢に戻ります。
    2. 2番目の選択肢footに一致し、のs直後に続くように成功しfoots、停止します。

いくつかのリソース

オンラインテスター


1
「2番目のバーを見つける」部分とはどういう意味ですか?式/文字列にはバーが1つだけあります。ありがとう
ziggy

2
@ziggyテストされる文字列は "foobarbarfoo"です。ご覧のとおり、文字列には2つのfooと2つのバーがあります。
スカイフット2014

4
誰かがいつアトミックグループが必要になるか説明できますか?最初の代替案とのみ照合する必要がある場合、なぜ複数の代替案を提供する必要があるのですか?
arviman 2017

2
この回答原子グループについてのより良い説明。誰かがここで編集してこの教訓的な答えを完成させることはできますか?
Peter Krauss

5
真剣な正規表現のチョップを必要とするプロジェクトにたどり着いたとき、この答えは不可欠であったことに注意してください。これは、ルックアラウンドの優れた簡潔な説明です。
トム・コフリン

215

ルックアラウンドはゼロ幅のアサーションです。彼らは正規表現をチェックし(現在の位置の右または左-前方または後方に基づいて)、一致が見つかったときに成功または失敗し(正か負かに基づいて)、一致した部分を破棄します。それらは文字を消費しません-それらがあればそれに続く正規表現のマッチングは同じカーソル位置から始まります。

読むregular-expression.info詳細については。

  • 肯定的な先読み:

構文:

(?=REGEX_1)REGEX_2

REGEX_1が一致する場合にのみ一致します。REGEX_1に一致した後、一致は破棄され、REGEX_2の検索は同じ位置から開始されます。

例:

(?=[a-z0-9]{4}$)[a-z]{1,2}[0-9]{2,3}

REGEX_1は[a-z0-9]{4}$、4つの英数字とそれに続く行末に一致します。
REGEX_2は[a-z]{1,2}[0-9]{2,3}、1つまたは2つの文字とそれに続く2つまたは3つの数字に一致します。

REGEX_1は文字列の長さが確かに4であることを確認しますが、文字を消費しないため、REGEX_2の検索は同じ場所で開始されます。ここで、REGEX_2は、文字列が他のいくつかのルールに一致することを確認します。先読みがないと、長さ3または5のストリングに一致します。

  • 否定先読み

構文:

(?!REGEX_1)REGEX_2

REGEX_1が一致しない場合にのみ一致します。REGEX_1を確認した後、REGEX_2の検索は同じ位置から始まります。

例:

(?!.*\bFWORD\b)\w{10,30}$

先読み部分FWORDは文字列のをチェックし、見つかった場合は失敗します。が見つからない場合FWORD、先読みは成功し、次の部分で文字列の長さが10から30の間で、単語文字のみが含まれていることを確認しますa-zA-Z0-9_

後読みは先読みに似ています。現在のカーソル位置の後ろを見るだけです。javascriptなどの一部の正規表現フレーバーは、後読みアサーションをサポートしていません。そして、それをサポートするほとんどのフレーバー(PHP、Pythonなど)では、後読み部分を固定長にする必要があります。

  • アトミックグループは基本的に、トークンが一致すると、グループ内の後続のトークンを破棄/忘れます。アトミックグループの例については、このページを確認してください

あなたの説明に従って、javascriptでは動作しないようです/(?=source)hello/.exec("source...hummhellosource ")= null。あなたの説明は正しいですか?
Helin Wang 2013

@HelinWangその説明は正しいです。あなたの正規表現は、ソースとhelloの両方である文字列を期待しています!
Amarghosh 2013年

@jddxf詳しく説明しますか?
Amarghosh

@Amarghosh私は「現在の位置の右または左に向かって-前方または後方に基づいて」正規表現をチェックし、一致が見つかったときに成功または失敗し(正か負かに基づいて)、一致したものを破棄します部分。"。したがって、先読みは現在の位置の右側に向かって正規表現をチェックする必要があり、
正の

@Amarghosh は後に来る(?=REGEX_1)REGEX_2場合にのみ一致ますか?REGEX_2 REGEX_1
aandis

0

ぐるぐる見回す急速に。
先読みと後読みを区別する方法は?私と一緒に2分のツアーに参加:

(?=) - positive lookahead
(?<=) - positive lookbehind

と思います

    A  B  C #in a line

今、私たちはBに尋ねます、あなたはどこにいますか?
Bには、場所を宣言するための2つのソリューションがあります。

1つは、BにAが先行し、Cがバインドされている
2つは、BがCの前(先読み)であり、Aの後ろ(先読み)である。

ご覧のとおり、2つのソリューションでは、前後が逆になっています。
正規表現はソリューション2です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.