1

I’ve regex a(boy)?(boycott)? testing against aboycott.

const result = "aboycott".match(/a(boy)?(boycott)?/);

console.log(result[0]);

My thought process

  • a matches with a
  • b matches with b
  • o matches with o
  • y matches with y
  • c doesn't matches with b

Since (boy) is optional so its state is saved and the REGEX engine can backtrack to try the saved state

  • b matches with b
  • o matches with o
  • y matches with y
  • c matches with c
  • o matches with o
  • t matches with t
  • t matches with t

The final match should be aboycott but it matches aboy. What is going on here? If I'm not wrong ? is greedy it first tries to match and the state is saved. If there is no match then backtrack to the saved place.

DecPK
  • 24,537
  • 6
  • 26
  • 42
  • ? is matches one or more, maybe you want * (zero or more). – m0skit0 Jul 22 '21 at 15:31
  • It does match, it matched `aboy` and so it doesn't match the rest. Maybe you meant to do: `"aboycott".match(/a(boy)?(cott)?/);` ? – Nir Alfasi Jul 22 '21 at 15:32
  • `boy` is a prefix of `boycott`. After matching `boy`, there is no way to match `boycott` as there is only `cott` left to match. If you swap them, you will match `aboycott`, `a(boycott)?(boy)?`. Or, you can use `a(?:boy(?:cott)?)?`. – Wiktor Stribiżew Jul 22 '21 at 15:32
  • 2
    @m0skit0 `?` matches `zero or one` – DecPK Jul 22 '21 at 15:36
  • You want the first optional capture group to be explicitly loose (lazy) by using double question marks: `a(boy)??(boycott)?` – MonkeyZeus Jul 22 '21 at 16:44

0 Answers0