I'm trying to write a user name validation that has the following restrictions:
The following examples are valid: abc123, my_name, 12345a
The following examples are invalid: 123456, my_name!, _1235
I found something about using positive lookaheads for the letter contraint: (?=.*[a-zA-Z]), and it looks like there could be some sort of negative lookahead for the second constraint, but I'm not sure how to mix them together into one regex. (Note... I am not really clear on what the .* portion does inside the lookahead...)
Is it something like this: /(?=.*[a-zA-Z])(?!.*[^a-zA-Z0-9_])/
Edit:
Because the question asks for a regex, the answer I'm accepting is:
/^[a-zA-Z0-9_]*[a-zA-Z][a-zA-Z0-9_]*$/
However, the thing I'm actually going to implement is the suggestion by Bryan Oakley to split it into multiple smaller checks. This makes it easier to both read and extend in the future in case requirements change. Thanks all!
And because I tagged this with ruby-on-rails, I'll include the code I'm actually using:
validate :username_format
def username_format
has_one_letter = username =~ /[a-zA-Z]/
all_valid_characters = username =~ /^[a-zA-Z0-9_]+$/
errors.add(:username, "must have at least one letter and contain only letters, digits, or underscores") unless (has_one_letter and all_valid_characters)
end
/^[a-zA-Z0-9_]*[a-zA-Z][a-zA-Z0-9_]*$/
: 0 or more valid characters followed by one alphabetical followed by 0 or more valid characters, constrained to be both the beginning and the end of the line.
It's easy to check whether the pattern has any illegal characters, and it's easy to check whether there's at least one letter. Trying to do that all in one regular expression will make your code hard to understand.
My recommendation is to do two tests. Put the tests in functions to make your code absolutely dead-simple to understand:
if no_illegal_characters(string) && contains_one_alpha(string) {
...
}
For the former you can use the pattern ^[a-zA-Z0-9_]+$
, and for the latter you can use [a-zA-Z]
.
If you don't like the extra functions that's ok, just don't try to solve the problem with one difficult-to-read regular expression. There are no bonus points awarded for cramming as much functionality into one expression as possible.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With