I can\'t figure out javascript regex that would satisfy all those requirements:
The string can only contain underscores and alphanumeric characters. It must
See regex in use here
^[a-z](?!\w*__)(?:\w*[^\W_])?$
^
Assert position as the start of the line[a-z]
Match any lowercase ASCII letter. The code below adds the i
(case-insensitive) flag, thus this also matches the uppercase variables(?!\w*__)
Negative lookahead ensuring two underscores do not exist in the string(?:\w*[^\W_])?
Optionally match the following
\w*
Match any number of word characters[^\W_]
Match any word character except _
. Explained: Match anything that is _
(since it's in the negated set).$
Assert position at the end of the linelet a = ['somestring', '_not_this_one', 'thisone_', 'neither this one', 'but_this_one', 'this__one_not', 'this_one__yes']
var r = /^[a-z](?!\w*__)(?:\w*[^\W_])?$/i
a.forEach(function(s) {
if(r.test(s)) console.log(s)
});
You could use multiple lookaheads (neg. ones in this case):
^(?!.*__)(?!.*_$)[A-Za-z]\w*$
See a demo on regex101.com.
^ # start of the line
(?!.*__) # neg. lookahead, no two consecutive underscores (edit 5/31/20: removed extra Kleene star)
(?!.*_$) # not an underscore right at the end
[A-Za-z]\w* # letter, followed by 0+ alphanumeric characters
$ # the end
JavaScript
snippet:
let strings = ['somestring', '_not_this_one', 'thisone_', 'neither this one', 'but_this_one', 'this__one_not', 'this_one__yes']
var re = /^(?!.*__)(?!.*_$)[A-Za-z]\w*$/;
strings.forEach(function(string) {
console.log(re.test(string));
});
Please do not restrain passwords!
You can also use
^[a-zA-Z]([a-zA-Z0-9]|(_(?!_)))+[a-zA-Z0-9]$
Demo
The only change comparing to your regex is changing [a-zA-Z0-9_]
to [a-zA-Z0-9]|(_(?!_))
. I removed underscore from the character set and allow it in the second part of the alternative if it's not followed by another one.
(?!_)
is negative lookahead meaning that _
cannot be next character