I can't completely wrap my head around combining positive lookaheads and backtracking in JavaScript. I read this answer, as well as this article and did some testing with https://regex101.com/, but don't quite get the result I'm expecting.
So given the test string banana12, the following works:
(?=\d{2,})
- assert that the string contains at least two digits(?=[a-z]{5,})
- assert that the string contains at least five lowercase characters
These two conditions work for both banana12 and 12banana.
However, when I try to combine the two (?=\d{2,})(?=[a-z]{5,})
, I don't get a match. In order to get a match when using banana12, I need to add \D*
to the digit-testing lookahead: (?=\D*\d{2,})(?=[a-z]{5,})
.
Why doesn't (?=\d{2,})(?=[a-z]{5,})
work?
If I change the test string to 12banan, to get a match I need to use: (?=\d{2,})(?=[^a-z]*[a-z]{5,})
- so this time no backtracking for the digits, backtracking for the lowercase letters.
So in general, if I want to make sure, that my regex matches correctly both strings (12banana, banana12), I need to use: (?=\D*\d{2,})(?=[^a-z]*[a-z]{5,})
.
Why? If both lookaheads work on their own, why don't they work in combination and why is it necessary to add backtracking?