これを試して:
r(?:(?!\1)a()|(?!\2)e()|(?!\3)i()|(?!\4)p()){4}r
...またはより読みやすく:
r
(?:
(?!\1) a () |
(?!\2) e () |
(?!\3) i () |
(?!\4) p ()
){4}
r
空のグループはチェック マークとして機能し、各文字が消費されるとチェックマークが付きます。たとえば、一致する単語が である場合、この構文によって一致する最初の文字はrepair
theになります。e
正規表現が後で別の正規表現と一致しようとするとe
、その代替は一致しません。グループ #2 が試合に参加しているため、否定的な先読み(?!\2)
は失敗します。
本当に素晴らしいのは、重複した文字を含む文字列でも同様に機能することです。あなたのredeem
例を見てください:
r
(?:
(?!\1) e () |
(?!\2) e () |
(?!\3) e () |
(?!\4) d ()
){4}
m
最初の選択肢が消費された後、e
最初の選択肢は事実上無効になるため、代わりに 2 番目の選択肢が使用されます。等々...
残念ながら、この手法はすべての正規表現で機能するわけではありません。1 つには、空/失敗したグループ キャプチャをすべて同じように扱うわけではありません。ECMAScript 仕様では、参加していないグループへの参照は常に成功する必要があると明示的に述べています。
正規表現フレーバーは、前方参照、つまり、正規表現で参照するグループの前に現れる後方参照もサポートする必要があります。( ref ) 私が知っている .NET、Java、Perl、PCRE、Ruby で動作するはずです。