Reputation: 714
I'm trying to achieve these rules with a regex:
Valid:
Spicy_Pizza
97Indigos
Infinity.Beyond
Invalid:
_yahoo
powerup.
un__real
no..way
Here's my current regex:
^(?:[a-zA-Z0-9]|([._])(?!\1)){3,28}$
All rules seem to be working other than the exception for starting and ending with underscores or periods.
Upvotes: 5
Views: 1534
Reputation: 110675
I prefer making clear that the string cannot begin or end with a period or underscore, as opposed to stipulating which characters are permitted at the beginning and end of the string.
r = /
\A # match beginning of string
(?![._]) # next char cannot be a period or underscore
(?: # begin non-capture group
[a-zA-Z0-9] # match one of chars in indicated
| # or
([._]) # match a period or underscore in capture group 1
(?!\1) # next char cannot be the contents of capture group 1
){3,28} # end non-capture group and execute non-capture group 3-28 times
(?<![._]) # previous char cannot be a period or underscore
\z # match end of string
/x # free-spacing regex definition mode
%w| Spicy_Pizza 97Indigos Infinity.Beyond _yahoo powerup. un__real no..way |.each do |s|
puts "%s: %s" % [s, s.match?(r) ? "valid" : "invalid"]
end
Spicy_Pizza: valid
97Indigos: valid
Infinity.Beyond: valid
_yahoo: invalid
powerup.: invalid
un__real: invalid
no..way: invalid
Upvotes: 1
Reputation: 370729
Sounds like you just need to add an alphanumeric check to the first and last character of the string. Because that will take up 2 characters, change the inner repetition from {3,28}
to {1,26}
:
^[A-Za-z\d](?:[a-zA-Z0-9]|([._])(?!\1)){1,26}[A-Za-z\d]$
^^^^^^^^^^ ^^^^ ^^^^^^^^^^
https://regex101.com/r/G6bVaZ/1
Upvotes: 4