0

I'm trying to find all the matches for 'test' in my string:

const search = "test";
const regexString = "(?:[^ ]+ ){0,3}" + "test" + "(?: [^ ]+){0,3}";
const re = new RegExp(regexString, "gi");
const matches = [];
const fullText = "my test string with a lot of tests that should match the test regex";
let match = re.exec(fullText);
while (match != undefined) {
    matches.push(match[1]);
    match = re.exec(fullText);
}
console.log(matches);

I'm getting the following:

[ undefined, undefined, undefined ]

Why isn't my search working?

CRice
  • 22,449
  • 3
  • 48
  • 54
Mary
  • 655
  • 11
  • 26

2 Answers2

4

Your code expects the result of the match to include stuff captured in capturing groups in the regular expression. However, your regular expression contains only non-capturing groups. The (?: ) grouping explicitly does not capture the matched substring.

You want plain ( ) groupings.

Pointy
  • 371,531
  • 55
  • 528
  • 584
  • Thanks. When I change to: const regexString = "([^ ]+ ){0,3}" + "test" + "( [^ ]+){0,3}"; I get: [ 'my ', 'of ', 'the ' ]. Is there a way to capture a few words before and after the 'test' search search? Sorry for beginner question regex confuses me. – Mary Apr 16 '18 at 22:32
  • @Mary right - your code expects there to be something in `match[1]`, but if there are no real capturing groups `match` will always be an array with just one value. Your code currently only looks at `match[1]`, but the regular expression (fixed) captures *two* groups, so you need to also look at `match[2]`. – Pointy Apr 16 '18 at 22:33
1

You should enclose your non-capturing groups (?:...) in a capturing group (...) since you are invoking a capturing group (match[1]). :

"((?:\\S+ ){0,3})" + search + "((?: \\S+){0,3})"

Trying to return an array containing the 3 words preceding and proceeding 'test'

Then you need to push both captured groups not one:

matches.push([match[1], search, match[2]]);
// `match[1]` refers to first capturing group
// `match[2]` refers to second CG
// `search` contains search word

JS code:

const search = "test";
const regexString = "((?:\\S+ ){0,3})" + search + "((?: \\S+){0,3})";
const re = new RegExp(regexString, "gi");
const matches = [];
const fullText = "my test string with a lot of tests that should match the test regex";
while ((match = re.exec(fullText)) != null) {
    matches.push([match[1], search, match[2]]);
}
console.log(matches);
revo
  • 43,830
  • 14
  • 67
  • 109
  • 1
    This, however, doesn't output correct data on overlapping matches. A workaround would be using a lookahead construct. – revo Apr 16 '18 at 22:40
  • Is worth mentioning that regex [doesn't support repeated capturing groups](https://stackoverflow.com/questions/43461376/regex-repeating-capturing-group) so the best approach is to capture the three words (from before and after) together in a bigger capturing group. – Rodrigo Ferreira Apr 16 '18 at 23:03
  • 1
    @RodrigoFerreira It's not the regex, it's the flavor. i.e. `.NET` supports accessing to quantified capturing groups, each one individually. – revo Apr 16 '18 at 23:06