たとえば、以下の正規表現は、後読みアサーションが固定長ではないことを報告する失敗を引き起こします。
#(?<!(?:(?:src)|(?:href))=["\']?)((?:https?|ftp)://[^\s\'"<>()]+)#S
先読みにはそのような制限はありません。
たとえば、以下の正規表現は、後読みアサーションが固定長ではないことを報告する失敗を引き起こします。
#(?<!(?:(?:src)|(?:href))=["\']?)((?:https?|ftp)://[^\s\'"<>()]+)#S
先読みにはそのような制限はありません。
先読みと後読みは、その名前が示すほど似ていません。先読み式は、現在の一致位置に固定され、一致するものを消費しないことを除いて、スタンドアロンの正規表現の場合とまったく同じように機能します。
後読みはまったく別の話です。現在の一致位置から開始して、一度に 1 文字ずつテキストを逆方向に進み、各位置でその式を一致させようとします。一致が不可能な場合、後読みはあきらめる前に、テキストの先頭 (一度に 1 文字ずつ、覚えておいてください) まで行かなければなりません。これを、1 回だけ適用される先読み式と比較してください。
もちろん、これは非常に単純化しすぎており、すべてのフレーバーがそのように機能するわけではありませんが、アイデアは理解できます。後読みが適用される方法は、先読みが適用される方法とは根本的に異なります (そして、はるかに効率的ではありません)。後読みがどれだけさかのぼって見なければならないかを制限することだけが理にかなっています。
まず第一に、これはすべての正規表現ライブラリ (.NET など) に当てはまるわけではありません。
PCRE の場合、次の理由が考えられます。
後読みアサーションの実装は、代替案ごとに、現在の位置を固定幅だけ一時的に戻し、一致を試みることです。
(少なくとも、http://www.autoitscript.com/autoit3/pcrepattern.htmlによると)。
PCRE は、重大なパフォーマンスの問題を引き起こす可能性があるため、浮動後読みをサポートしていません。これは、右から左へのマッチング機能がないためです。PCRE は固定された左からのみ分岐を開始できますが、可変長後読みの左は固定できません。
一般に、可能であれば、後読み部分を固定長パターンに分岐するようにしてください。たとえば、次の代わりに:
(?<=(src|href)=")etc.
(1)これを使用します:
(?:(?<=src=")|(?<=href="))etc.
(2)または\K
:
(src|href)="\Ketc.
は常に前の一致の最後で検索を開始するため、実際の後読みではないことに注意してください\K
(前の一致への潜在的なバックステップはありません)。
(3)複雑な後読みのみのケースでは、逆文字列で「逆」先読み式を使用して検索できます。あまりにもエレガントではありませんが、うまくいきます:
.cte(?="=(ferh|crs))
同じ問題があり、使用して修正しました (?: subexpression)
非キャプチャ グループを定義します。
Write(?:Line)?
「Console.WriteLine()」の「WriteLine」「Console.Write(value)」の「Write」など
以下の正規表現を変更する,
必要がありました.
(?<=,|^)
これとともに、
(?:(?<=,)|^)