Help understanding the behavior of this regex

What is going on here?

Challenge: Regular Expressions - Positive and Negative Lookahead

My problem:
I’ve already “solved” this exercise (i.e. I’ve stumbled upon a solution that passes the test), but I cannot for the life of me figure out why. I’ve googled for more information on how lookaheads function and searched around this forum for examples, but I have been unable to find any answers.

The given criteria:
Use lookaheads in the pwRegex to match passwords that are greater than 5 characters long, and have two consecutive digits.

What I expected to work:

let pwRegex = /(?=.{6})(?=\d{2})/;

What actually works:

let pwRegex = /(?=.{6})(?=\D*\d{2})/;

Without the \D* added, I get these console messages:

Your regex should match the string bana12
Your regex should match the string abc123
Your regex should match the string 8pass99
Your regex should match the string astr1on11aut

I don’t understand how checking for zero or more non-digit characters before the two digits makes the difference, and further experimentation hasn’t yielded any answers, which leads to my question:

What is actually going on here?

Complete code that ‘solves’ the challenge:

let sampleWord = "astronaut";
let pwRegex = /(?=.{6})(?=\D*\d{2})/; // Change this line
let result = pwRegex.test(sampleWord);

My browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36

I find this site very helpful in understanding what’s happening with regex: https://regex101.com/

I think the difference here is using a * (at least 1 match) versus a specific number {2}

(?=.{6})(?=\d*)

This works to find abc123, for example

The reason behind the {2} is to ensure the password follows the second criteria: two consecutive digits. It prevents matching of invalid passwords like ‘banan1’.

Also, somebody correct me if I’m wrong, but in this context {2} is functionally the same as {2,}, right? Searching for at least one instance of a sequence of two consecutive digits produces the same result as searching for at least one instance of a sequence of two or more consecutive digits.

(?=.{6})(?=.*\d{2})

This works for abc123. I think because the ?= lookahead starts from the beginning each time?

The first section matches 6 characters, but the second section sees “abc123”, it can’t match because the whole sequence “abs123” doesn’t match (?=\d{2}) 2 digits. It does match "any # of char preceding at least 2 digits though (?=.*\d{2})

Asserts that the given subpattern can be matched here, without consuming characters

It matches the string, but doesn’t move the “cursor” forward through the string to the next section.

The reason your \D* works is because it matches the “abc” first, then it can match the 2 digits.

Too long to explain again. Recycling answer from another post . :slight_smile:

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.