肯定的な先読みの中に否定的な先読みを入れる必要があります。
(?<![A-Z])[A-Z]{3}.(?=[A-Z]{3}(?![A-Z]))
後読みでもそれを行うことができます:
(?<=(?<![A-Z])[A-Z]{3}).(?=[A-Z]{3}(?![A-Z]))
ルックアラウンド自体は文字を消費しないため、「固定長の後読み」ルールに違反しません。
編集(固定長の後読みについて):後読みをサポートするすべてのフレーバーの中で、Python は最も柔軟性がありません。ほとんどのフレーバー (Perl、PHP、Ruby 1.9+ など) では、次を使用できます。
(?<=^[A-Z]{3}|[^A-Z][A-Z]{3}).
...正確に 3 つの大文字の ASCII 文字が前にある文字に一致します。最初の選択肢 - - 3ポジション後ろ^[A-Z]{3}
を探し始めるのに対し、2 番目 - - は正確に4ポジション戻る。Java では、これを次のように減らすことができます。[^A-Z][A-Z]{3}
(?<=(^|[^A-Z])[A-Z]{3}).
...コンパイル時に少し余分な作業を行って、後読みの最大長が 4 桁になることを確認するためです。そして、.NET と JGSoft では何でもありです。どこでも合法であれば、後読みでも合法です。
しかし、Python では、後読み部分式は単一の固定数の文字と一致する必要があります。その制限に何度か頭をぶつけたことがあれば、次のようなことがうまくいくとは思わないかもしれません。
(?<=(?<![A-Z])[A-Z]{3}).
少なくとも私はしませんでした。Java バージョンよりもさらに簡潔です。Pythonでどのように機能しますか? しかし、Python や、後読みをサポートする他のすべてのフレーバーでは機能します。
いいえ、どんなフレーバーでも先読みに同様の制限はありません。