8

最近の多くの正規表現の質問には、一致の成功に必要ではないように思われるクエリにある種のルックアラウンド要素があります。それらを推進している教育リソースはありますか?私は、どのような場合にポジティブなルック・アヘッド/ビハインドを使用した方がよいかを理解しようとしています. 私が見ることができる主なアプリケーションは、要素を一致させようとするときです。しかし、たとえば、最近の質問からのこのクエリには、 をキャプチャするための簡単な解決策があり.*ますが、なぜ後方参照を使用するのでしょうか?

(?<=<td><a href="\/xxx\.html\?n=[0-9]{0, 5}">).*(?=<\/a><span

そして、これは別の質問からのものです:

$url = "www.example.com/id/1234";
preg_match("/\d+(?<=id\/[\d])/",$url,$matches);

前向きなルックアラウンドを使用する方が本当に良いのはいつですか? いくつか例を挙げていただけますか?

これは意見に基づく質問に近いと思いますが、答えは本当に有益だと思います. 正規表現は、物事を複雑にしなくても十分に混乱します...私はこのページを読んで、それらがどのように機能するかよりも、いつ使用するかについてのいくつかの簡単なガイドラインにもっと興味があります.


すべての返信に感謝します。以下に加えて、ここでm.buettner の素晴らしい回答をチェックすることをお勧めします。

4

8 に答える 8

1

私はあなたのポイントに対処しようとします:

  • 私に見えるクエリのある種のルックアラウンド要素は、一致の成功には必要ありません

    もちろん試合には必要です。ルックアラウンド アサーションが失敗するとすぐに、一致はありません。これらは、パターンの周囲の条件を保証するために使用でき、さらに true にする必要があります。次の場合にのみ、正規表現全体が一致します。

    1. パターンはフィットし、

    2. ルックアラウンド アサーションは true です。

    ==> しかし、返される一致はパターンのみです。

  • 前向きなルックアラウンドを使用する方が本当に良いのはいつですか?

    簡単な答え: 何かをそこに置きたいが、一致させたくない場合です!

    Bergi が彼の回答で述べたように、それらはゼロ幅のアサーションです。つまり、文字シーケンスと一致しないことを意味し、文字シーケンスが存在することを保証するだけです。そのため、ルックアラウンド式内の文字は「消費」されず、正規表現エンジンは最後の「消費」文字の後に続行されます。

  • 最初の例について:

    (?<=<td><a href="\/xxx\.html\?n=[0-9]{0, 5}">).*(?=<\/a><span
    

    あなたの側に誤解があると思います. " は "をキャプチャする簡単な解決策を持ってい.*ます. は.*「キャプチャ」されたものではなく、式が一致する唯一のものです。<td><a href="\/xxx\.html\?n=[0-9]{0, 5}">ただし、前に" " があり、後ろに " " がある文字のみが一致します<\/a><span(これらの 2 つは一致の一部ではありません! )。

    「キャプチャ済み」は、キャプチャ グループによって一致したもののみです。

  • 2番目の例

    \d+(?<=id\/[\d])
    

    は興味深い。一連の数字 ( \d+) に一致し、一連の後に、後読みアサーションは、その前に "id/" を持つ数字が1 つあるかどうかをチェックします。複数の数字がある場合、または数字の前のテキスト「id/」が欠落している場合、失敗することを意味します。前に適切なテキストがある場合、この正規表現が 1 桁のみに一致することを意味します。

  • 教材

于 2013-10-09T08:48:37.443 に答える
1

ルックアラウンドの適切な使用法を理解しており、明確な理由もなく使用されている理由を尋ねていることを前提としています。

人々が正規表現を使用する方法には、主に 4 つのカテゴリがあると思います。

検証
検証は通常、テキスト全体に対して行われます。あなたが説明したようなルックアラウンドは不可能です。

一致テキストの一部
を 抽出します。ルックアラウンドは、主に開発者の怠惰のために使用されます:キャプチャを回避します。 たとえば、設定ファイルに行がある場合、一致して最初のグループを取得するか、一致してすべてを取得できます。 他の回答が言ったように、一致間でオーバーラップが必要になる場合がありますが、これらは比較的まれです。
Index=5/^Index=(\d+)//(?<=^Index=)\d+/

置換
これは一致と似ていますが、1 つの違いがあります。一致全体が削除され、新しい文字列 (およびいくつかのキャプチャされたグループ) に置き換えられます。
例: の名前を強調表示したい"Hi, my name is Bob!"
に置き換えることもできますが、 - に置き換える方がきれいで、/(name is )(\w+)/キャプチャはまったくありません。$1<b>$2</b>
/(?<=name is )\w+/<b>$&</b>

Split
splitはテキストを取得し、パターンを区切り文字としてトークンの配列に分割します。これは次の方法で行われます。

  • を見つけますmatch。この試合の前はすべてトークンです。
    • 一致の内容は破棄されますが、次のようになります。
    • ほとんどのフレーバーでは、一致でキャプチャされた各グループもトークンです (特に Java ではそうではありません)。
  • 一致するものがなくなると、残りのテキストが最後のトークンになります。

ここでは、ルックアラウンドが重要です。文字の一致とは、結果からその文字を削除するか、少なくともトークンから分離することを意味します。
例: 引用符で囲まれた文字列のカンマ区切りのリストがあります:"Hello","Hi, I'm Jim."
カンマによる分割/,/は間違っています: { "Hello", "Hi, I'm Jim."}
引用符を追加できません/",/: { "Hello, "Hi, I'm Jim."}
唯一の適切なオプションは後読みです/(?<="),/: { "Hello", "Hi, I'm Jim."}

個人的には、可能であれば、区切り文字で分割するよりもトークンを一致させることを好みます。

結論

主な質問に答えるために-これらのルックアラウンドが使用される理由は次のとおりです。

  • 必要なテキストを一致させることができない場合があります。
  • 開発者はシフトレスです。
于 2013-10-09T12:31:32.037 に答える
1

Lookaround assertions正規表現のパフォーマンス低下backtrackingの主な原因となる可能性のあるものを減らすためにも使用できます。

例: 正規表現^[0-9A-Z]([-.\w]*[0-9A-Z])*@(1) は、^[0-9A-Z][-.\w]*(?<=[0-9A-Z])@(2) ポジティブ ルック ビハインド (電子メール アドレスのユーザー名の単純な検証) を使用して記述することもできます。

正規表現 (1) は、ネストされた量指定子[0-9A-Z]のサブセットであるため、本質的に多くのバックトラッキングを引き起こす可能性があります。[-.\w]Regex (2) は、過剰なバックトラッキングを減らします。詳細については、バックトラッキングセクションバックトラッキングの制御 > 後読みアサーションを参照してください。

詳細については、backtracking

于 2013-10-10T12:40:53.700 に答える