1

My problem

I've been confused by the following code snippet. The strings seems identical regex-wise (the only difference is a digit that should be matched with \d. In essence, the first string is matched while the second does not.

After playing around with it, it became clear that the order matters: only the first string is matched.

const regex = /departure\stime\s+([\d:]+)[\s\S]*arrival\stime\s+([\d:]+)[\s\S]*Platform\s+(\S+)[\s\S]*Duration\s([\d:]+)/gm;
const s1 = '\n                                departure time 05:42\n                                \n                                arrival time 06:39\n                                Boarding the train from Platform 3\n                                \n                                    Switch train in \n                                    No changing\n                                    \n                                        Change\n                                        \n                                    \n                                \n                                \n                                    Access for handicapped.\n                                    reserved seats\n                                \n                                \n                                    Duration 00:57\n                                \n                            ';
const s2 = '\n                                departure time 05:12\n                                \n                                arrival time 06:09\n                                Boarding the train from Platform 3\n                                \n                                    Switch train in \n                                    No changing\n                                    \n                                        Change\n                                        \n                                    \n                                \n                                \n                                    Access for handicapped.\n                                    reserved seats\n                                \n                                \n                                    Duration 00:57\n                                \n                            ';
console.log('Match:   ', regex.exec(s1));
console.log('No Match:', regex.exec(s2));

My question

How can I use the same regex to match multiple strings, without worrying that the previous match might alter the match?

Adam Matan
  • 128,757
  • 147
  • 397
  • 562
  • 1
    Note that the behaviors of `String.prototype.match()` and `RegExp.prototype.exec()` are quite different with respect to what the `g` flag does. Why are you using the "g" flag at all? Have you tried *without* "g"? – Pointy Dec 11 '17 at 15:42
  • 1
    Either you need to manually reset lastIndex or you should be using match – epascarello Dec 11 '17 at 15:43
  • You need to make your quantifiers lazy: [`departure\stime\s+([\d:]+)[\s\S]*?arrival\stime\s+([\d:]+)[\s\S]*?Platform\s+(\S+)[\s\S]*?Duration\s([\d:]+)`](https://regex101.com/r/nVD9fT/1) – ctwheels Dec 11 '17 at 15:44
  • Use `String.prototype.match` instead of `RegExp.prototype.exec`. – Jared Smith Dec 11 '17 at 15:44
  • 1
    Possible duplicate of [How to make Regular expression into non-greedy?](https://stackoverflow.com/questions/2824302/how-to-make-regular-expression-into-non-greedy) – ctwheels Dec 11 '17 at 15:45

1 Answers1

1

When you use the 'g' flag in your regex, .exec() will return an index into the lastIndex property on the regex object. Then, when you attempt to use .exec() again with the same regex, it will begin the search at the index specified in lastIndex.

There are a few ways to overcome this:

1) Remove the 'g' flag. lastIndex will stay set at 0
2) Use .match(), .test(), or .search()
3) Manually reset the lastIndext after each call to .exec()
    // for example:
    let results = regex.exec(s1);
    regex.lastIndex = 0;

See the docs here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec

Cruiser
  • 1,618
  • 2
  • 16
  • 20