1

I'm trying the following regex /(?<=.*)(\w\w)(?=.*)/ in the console of my browser.

I read this regex as follows: "find and capture any two alphanumeric chars preceded and followed by zero or more occurence of any char".

With "abcde" as input I would expect my browser to match "ab", "bc", "cd" and "de".

Why is it just giving me "ab" and "cd"?

Is there a way to make a regex return all the matches that I want ("ab", "bc", "cd" and "de")?

I know what a lookarounds are used for, and I've already seen How does the regular expression ‘(?<=#)[^#]+(?=#)’ work?. Lookbehind is supported in Google Chrome since 2018-2019.

Thanks in advance

Some console statements

Fredo Corleone
  • 544
  • 1
  • 6
  • 16

2 Answers2

2
  1. /(?<=.*)(\w\w)(?=.*)/ is the same as /(\w\w)/ because "preceded and followed by zero or more occurence" always matches in any case (as it matches an empty string).

  2. Unlike zero-length assertions (\b, $, (?=), etc), all other expressions are non-zero-length, i.e. they consume a bite of their length from the string. There is some search cursor that proceeds by this length and never steps back. If 2 symbols are found then this cursor proceeds by 2 symbols, and the search goes on.

For described behavior you need to move this cursor manually like this:

const str = 'abcde';

const re = /(\w\w)/g;

let result;

while (result = re.exec(str)) {
  console.log(result);
  re.lastIndex--;
}
vsemozhebuty
  • 12,992
  • 1
  • 26
  • 26
1

So in-order to find overlapping matches, you have to put the desired pattern inside a lookahead.

(?=(\w\w))

Regex DEMO

Example:

const regex = /(?=(\w\w))/gm;
const str = `abcde`;
let m;
let matches = [];

while ((m = regex.exec(str)) !== null) {
    // This is necessary to avoid infinite loops with zero-width matches
    if (m.index === regex.lastIndex) {
        regex.lastIndex++;
    }
    
    // The result can be accessed through the `m`-variable.
    m.forEach((match, groupIndex) => {
        if (groupIndex === 1) {
         matches.push(match);
        }
    });
}
console.log(matches);
Avinash Raj
  • 172,303
  • 28
  • 230
  • 274