Home > Back-end >  REGEX Pattern skips every other entry
REGEX Pattern skips every other entry

Time:10-07

I have two REGEX patterns to read MGRS grid coordinate data entered by a user. One is for no spaces:

/\d{1,2}[^ABIOYZabioyz][A-Za-z]{2}([0-9][0-9]){0,5}/g

example coordinates entered would be:

  • 41ULB1782314279
  • 39UXV1859553744
  • 38UPG0622505396

whitespace separated or comma separated works fine.

And the other is for spaces in the coordinate:

/\d{1,2}[^ABIOYZabioyz]\s?[A-Za-z]{2}\s?([0-9]{0,5}\s?[0-9]){0,5}/g

Examples grids would look like:

  • 31P DL 90780 43331
  • 31P DL 9079 4333
  • 31P DL 907 433
  • 31P DL 90 43
  • 31P DL 9 4

The issue with the regex pattern looking for grid coordinates with spaces in them is that it is seeming to skip over every other coordinate entered, or skip coordinates randomly. I'm still new to REGEX and am not seeing where my issue is. The second REGEX pattern which looks for spaces is exactly identical to the one without spaces other than the fact I added in a few places to look for white space.

It works fine when users add commas between the grid coordinates with spaces in them, but if they only separate the grids with white space it skips over grids.

Any help would be appreciated as I have been at this for the better part of a day.

CodePudding user response:

When using /g on a regex, it maintains a lastIndex property that contains the last index matched. When you call exec again it will start looking at lastIndex 1. You can either reset lastIndex to -1, or drop the /g from the regexp.

const re = new RegExp(/\d{1,2}[^ABIOYZabioyz]\s?[A-Za-z]{2}\s?([0-9]{0,5}\s?[0-9]){0,5}/g);

['31P DL 90780 43331',
'31P DL 9079 4333',
'31P DL 907 433',
'31P DL 90 43',
'31P DL 9 4'].forEach((el) => {
    console.log(re.exec(el));
});

['31P DL 90780 43331',
'31P DL 9079 4333',
'31P DL 907 433',
'31P DL 90 43',
'31P DL 9 4'].forEach((el) => {
    re.lastIndex = -1;
    console.log(re.exec(el));
});
   

CodePudding user response:

If you don't need to check the pattern to be semantically correct, use this:

(\d{1,2}[^ABIOYZabioyz](?<space> ?)[A-Za-z]{2}(?:(?:\k<space>)\d{1,5}){2})

It works with or without space. If pattern had space after first part (?<space> ?), it should repeat two more time (?:\k<space>). \k<space> matches the same text captured by (?<space> ?) that is either one space or nothing.

regex demo

CodePudding user response:

In your first pattern, you repeat 0-5 times pairs of digits with ([0-9][0-9]){0,5} so it can also be optional.

In the second pattern, this part ([0-9]{0,5}\s?[0-9]){0,5} matches too much as the quantifier is 0-5 times for the whole group and can also match 5 times 5 digits, a whitespace char and a digit.

If that last part in the second pattern can also be optional, then you have to change the quantifier {0,5} from the group to the digits instead.

Note that \s? matches an optional whitespace char, and could also match a newline. The negated character class [^ can also match a newline.

\d{1,2}[^ABIOYZabioyz]\s?[A-Za-z]{2}\s?([0-9]{0,5}\s?[0-9]{0,5})
                                                          ^^^^^    

Regex demo

  • Related