Reputation: 4834
I'm trying to create a Regex. The rules are:
1) Only letters (both upper and lower), numbers, periods (.) and underscores (_)
2) Must begin and end with letter or number (i.e. no periods/underscores)
3) Cannot have multiple punctuations in a row, of any kind (no .. or ._ or _. or __ or .._. etc)
4) Must contain at least 2 letters (either upper or lower or both, doesn't matter)
5) No less than 3 chars, no more than 25 chars
So far, what I have is:
^((?!.*[\._]{2})[A-Za-z0-9\._]{3,25})$
Which is close-ish. I've got rules 1, 3 and 5, but cannot figure out 2 and 4.
I thought that
(([A-Za-z0-9]?)([A-Za-z0-9\._]+)([A-Za-z0-9]?)){3,25}
would get rule 2, but it just breaks it.
I've been working on this for a couple hours, but none of the solutions I can find, or can come up with, are quite what I'm looking for.
An explanation of the Regex statement you provide would be greatly appreciated, but is not entirely necessary.
EDIT 1
As per noob's suggestion:
^((?!.*[\._]{2})(([\w\d\.]+)){3,25})$
EDIT 2
Valid:
1rockit.man
q3w
e4.45r.d.2
sp_am
(and anything else between 3 and 25 characters, without leading or repeating punctuation)
Invalid:
.ret.
123
12a
ret..wer
super_.duper
_petrat
petrat_
Upvotes: 2
Views: 1315
Reputation: 18515
Takin part in ur riddle challenge. Here's my version. Would have nice performance as well :)
/^(?=(?:.*?[a-z]){2})[a-z\d](?!.*?[._]{2})[\w.]{1,23}[a-z\d]$/i
i
flag for caseless matching where [a-z]
is equivalent with alpha [a-zA-Z]
.
\w
is a short for word character [A-Za-z0-9_]
thus [\w.]
will match allowed characters.
(?:
opens a non capturing group mostly used for repitition or alternation (if group not needed).
(?=
(?!
lookarounds are zero-length assertions triggered at a certain position.
[a-z\d]
at ^
start and one at $
end[\w.]{1,23}
(?!.*?[._]{2})
no consecutive punctuation checked by negative lookahead.(?=(?:.*?[a-z]){2})
at least 2 letters checked with positive lookahead.Upvotes: 1
Reputation: 1689
You can try with:
^(?=.*[a-zA-Z].*[a-zA-Z].*)[a-zA-Z0-9](?!.*[._]{2,}|.*[._]$)[._a-zA-Z0-9]{2,24}$
or, if you prefer make it using character classes like \w \d \s, you could use:
^(?=.*[a-zA-Z].*[a-zA-Z].*)\w(?!.*[._]{2,}|.*[._]$)(\w|[._]){2,24}$
Upvotes: 1
Reputation: 22322
Building the regex from the rules (in an order of convenience):
//i
[\w.]*
^[\w.]{3,25}$
(?!^[\W_]|[W_]$)
\W
meaning not \w
)(?![\W_]{2})
(?:(?!...)[\w.]){3,25}
(?:)
instead of ()
because we don't need to save the group)(?:.*[a-z]){2}
assuming i
flag(?=(?:...))
The final regex literal:
/^(?=(?:.*[a-z]){2})(?:(?!^[\W_]|[\W_]{2}|[\W_]$)[\w.]){3,25}$/i
https://regex101.com/r/yK1cB3/5#javascript
x
flag (ignoring whitespace inside the regex), you could make it more readable (see a workaround for javascript):
^
(?=
(?:.*[a-z]){2}
)
(?:
(?!^[\W_]|[\W_]{2}|[\W_]$)
[\w.]
){3,25}
$
Upvotes: 4
Reputation:
Based upon your conditions I came up with following regex. It's only modification over your current regex.
Regex: ^(?=.*[A-Za-z].*[A-Za-z])([A-Za-z0-9]((?!.*[\._]{2})([\w\d\.]{1,23}))[A-Za-z0-9])$
Explanation:
The first part (?=.*[A-Za-z].*[A-Za-z])
checks for whole string to have two
characters separated by anything (that's pretty much the case here).
I added checks on the beginning and end of string which should be either letter or number.
Apart from that the length will also vary now as first and last character is counted rest of the length will be only 23 characters.
Upvotes: 7