1

Following usernames should be allowed:

Foo-Bar
Foobar
Fooo_123
Foob123_1
Foo-bar-123

Following user names should not be allowed:

_Foobar_
F-o-o-b-a-r
-Foobar-
_-Foobar-_

This means: The string is allowed to be 3 to 20 characters long. There is only one dash or underscore allowed every three characters. Not at the beginning and not and the end. You are only allowed to use at most 2 of a dash or underscore, a maximum of 3 numbers, but a minimum of 3 letters.

This is the Regexp I've done so far, but I already failed at allowing dashes at the front and end:

/^[^\-_][a-zA-Z0-9]{3,20}[^\-_]$/

Thanks in advance!

2 Answers 2

3

This is probably too complicated for a single regex, and if you could make one, it would be overly unreadable and complex. I suggest you simply have multiple checks; for example:

valid = str.length >= 3 && str.length <= 20        # or str.length.between? 3, 20
        && str =~ /^[^-_]+([-_][^-_]{3,})*[-_]?[^-_]+$/
        && str.count '-_' <= 2
        && str.count '0-9' <= 3
        && str.count 'A-Za-z' >= 3

Explanation of the regex:

/
  [^-_]+      # any amount of non-dashes/underscores (so it can't start with one)
  (
    [-_]      # a dash/underscore
    [^-_]{3,} # 3 or more non-dashes/underscores
  )
  *           # zero or more times
  [-_]?       # an optional dash/underscore
  [^-_]+      # any amount of non-dashes/underscores (so it can't end with one)
/x
Sign up to request clarification or add additional context in comments.

7 Comments

+1. Trying to make a kitchen-sink pattern is a slow descent into madness. I much rather prefer seeing several small, easily digestible, patterns, especially when I'm going to have to look at someone else's code.
Since you use the negative character class [^-_] the pattern allows any special characters (#!^$*%...). To ensure that there is only dashes, underscores, letters and digits you must change it to [a-zA-Z0-9] or [^\W_]. Another thing, why not using valid = str.length.between?(3, 20) (not tested)?
@CasimiretHippolyte Where does it say special characters are not allowed? I suppose I could use between?; I'll edit the post
@Doorknob: You are right, it is said nowhere! I have assumed by the numbers that there isn't special characters by reading the example strings! However it can be a false assumption.
@Just If you removed it, though, you wouldn't be able to use dashes or underscores at all!
|
0

I would suggest you start with /^(?![-_])[-_a-zA-Z0-9]{3,20}(?<![-_])$/, which will allow all of your ok-usernames and only one of the not-ok (see rubular for details). Then continue as Doorknob suggested and impose limits on the frequencies - and _ are used, ...

How - and _ at beginning and end are suppressed?

  • (?![-_]) ensures the next character is neither a - nor _
  • (?<![-_]) ensures the previous character is neither a - nor _

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.