Reputation: 33
I was doing Freecodecamp RegEx challange, which's about:
Use lookaheads in the pwRegex to match passwords that are greater than 5 characters long, do not begin with numbers, and have two consecutive digits
So far the solution I found passed all the tests was:
/^[a-z](?=\w{5,})(?=.*\d{2}\.)/i
However, when I tried
/^[a-z](?=\w{5,})(?=\D*\d{2,}\D*)/i
I failed the test trying to match astr1on11aut
(but passed with astr11on1aut
). So can someone help me explaining how ?=\D*\d{2,}\D*
failed this test?
Upvotes: 3
Views: 1246
Reputation: 4548
\d{2,}
Then let's have a look at the regexp match process
/^[a-z](?=\w{5,})
means start with [a-z], the length is at least 6, no problem.
(?=\D*\d{2,}\D*)
means the first letter should be followed by these parts:
[0 or more no-digit][2 or more digits][0 or more no-digits]
and lets have a look at the test case
astr1on11aut
// ^[a-z] match "a"
// length matchs
// [0 or more no-digit]: "str"
// d{2,} failed: only 1 digit
the ?=
position lookahead means exact followed by.
The first regular expression is wrong, it should be
/^[a-z](?=\w{5,})(?=.*\d{2}.*)/i
Upvotes: 3
Reputation: 163632
So can someone help me explaining how
(?=\D*\d{2,}\D*)
failed this test?
Using \D
matches any char except a digit, so from the start of the string you can not pass single digit to get to the 2 digits.
Explanation
astr1on11aut astr11on1aut
^ ^^
Can not pass 1 before reaching 11 Can match 2 digits first
Note
the expression could be shortened to (?=\D*\d{2})
as it does not matter if there are 2, 3 or more because 2 is the minimum and the \D*
after is is optional.
the first expression ^[a-z](?=\w{5,})(?=.*\d{2}\.)
can not match the example data because it expects to match a .
literally after 2 digits.
Upvotes: 3
Reputation: 627537
When it comes to lookahead usage in regex, rememeber to anchor them all at the start of the pattern. See Lookarounds (Usually) Want to be Anchored. This will help you avoid a lot of issues when dealing with password regexps.
Now, let's see what requirements you have:
(?=.{6})
(it requires any 6 chars other than lien break chars immediately to the right of the current location)(?!\d)
(no digit allowed immediately to the right)have two consecutive digits
=> (?=.*\d{2})
(any two digit chunk of text is required after any 0 or more chars other than line break chars as many as possible, immediately to the right of the current location).So, what you may use is
^(?!\d)(?=.{6})(?=.*\d{2})
Note the most expensive part is placed at the end of the pattern so that it could fail quicker if the input is non-matching.
See the regex demo.
Upvotes: 2