You can use this (see on rubular.com):
^(?=[1-4]{4}$)(?!.*(.).*\1).*$
The first assertion ensures that it’s ^[1-4]{4}$
, the second assertion is a negative lookahead that ensures that you can’t match .*(.).*\1
, i.e. a repeated character. The first assertion is “cheaper”, so you want to do that first.