Это будет решение для регулярных выражений, решите самостоятельно, является ли оно читабельным / пригодным для использования / обслуживаемым для вас.
(?!^.*?([@'_-]).*\1.*$)^(?! )[\w. @'-]{3,24}(?<! )$
См. здесь, в Regexr
(?!^.*?([@'_-]).*\1.*$)
является негативным прогнозом, если один из названных вами символов найден, он помещается в группу захвата 1, и для гарантии того, что это не повторяется, используется обратная ссылка \1
.
^(?! )
являетсяотрицательный взгляд, чтобы убедиться, что после начала строки нет пробела.
[\w. @'-]{3,24}
Символы, которые вы допускаете по крайней мере 3, максимум 24 из них
(?<! )$
- отрицательный взгляд заубедитесь, что до конца строки нет пробела.