What is wrong in my regex /(?=^[a-z]+\d{2,})(?=\w{5,})/ pattern?

617 Views Asked by At

This regex has to match passwords that are greater than 5 characters long, do not begin with numbers, and have two consecutive digits.

All the test cases are passing the regex test.

My regex is /(?=^[a-z]+\d{2,})(?=\w{5,})/

I have to use two positive lookaheads to solve this problem to pass the tests.

But astr1on11aut is not passing the test. Why?

Link to problem- https://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures/regular-expressions/positive-and-negative-lookahead

4

There are 4 best solutions below

0
VLAZ On BEST ANSWER

Your regex fails because of the first lookahead pattern (?=^[a-z]+\d{2,}). The string "astr1on11aut" starts with lowercase letters:

astr1on11aut
^^^^

This matches ^[a-z]+. However, the next part of the pattern demands two or more digits with \d{2,}, however the string only has one at that place:

   astr1on11aut
       ^^
       ||
digit -+|
        + --- not a digit

This causes the first lookahead pattern to fail.

You can express the validation rules more cleanly with three lookaheads:

  • "greater than 5 characters long: (?=.{5,})
  • "do not begin with numbers": ^(?!\d)
  • "and have two consecutive digits": (?=.*\d{2})

If we put them all together we get /(?=.{5,})(?!^\d)(?=.*\d{2})/

const regex = /^(?=.{5,})(?!\d)(?=.*\d{2})/;

test("abc");
test("123");
test("123abc");

test("abc123");
test("astr1on11aut");

test("., ;_'@=-%");
test("., ;_'@123=-%");

function test(string) {
  console.log(`${string} : ${regex.test(string)}`);
}

Note that this regex doesn't require letters. Strictly following the requirements, the only thing explicitly asked for is digits. Since the type of any other input is not specified, it's left to be anything (using .). It's best not to make too many assumptions when writing a regular expression or you might block legitimate input.

3
knittl On

If you are not limited to using a single regex, I suggest splitting this into multiple tests in your host language (e.g. JavaScript):

if (input.match(/^\D/)
    && input.match(/\d{2}/)
    && input.length >= 5) {
  // password policy fulfilled
}
0
Chris Ruehlemann On

Does this work for you?

(?=^\D.{5,}$).*(?=\d{2,})

The first lookahead asserts that the string must not begin with a digit but be at least 6 chars long; the second asserts that there must be at least 2 consecutive digits.

0
Kirill_S On

This regexp passes all the tests

/(?=\w*\d\d)(?=\w{5,})(?=^[^0-9]\w*)/

I believe you could fix yours by splitting the first group.