1

I'm attempting to regex match various duration strings (e.g. 1d10h, 30m, 90s, etc.) and have come up with a regex string to split the string into pieces, but it seems that I'm getting two undefined results at the ends that shouldn't be there. I imagine it has to do with the greedy matching via the ? groupings, but I'm not sure how to fix it.

My code looks like this:

const regex = /^(\d+?[d])?(\d+?[h])?(\d+[m])?(\d+[s])?$/gmi
const results = regex.exec('1d10h')

and the results I get look like so:

[
  "1d10h",
  "1d",
  "10h",
  undefined,
  undefined,
]

I was only expecting the first three results (and in fact, I only really want 1d and 10h) but the two remaining undefined results keep popping up.

1
  • 2
    You have 4 capture groups, and since they're optional, you'll have to filter out the undefineds manually afterwards Commented Aug 29, 2020 at 15:54

1 Answer 1

1

You have 4 groups in the regular expression - each enclosed with braces ( ... ) and enumerated naturally - the earlier opening brace appear in the expression the lower order index a group has.

And, of course, the whole match that could be named a "zero" group.

So, result of regex.exec('1d10h') contains 5 items:

  • results[0] - the whole expression match
  • results[i] - match of each group, i in {1,2,3,4}

Since in this case each group is optional (followed by ?) - it is allowed to have undefined in place of any unmatched group.

It is easy to see that if you remove a ? symbol after an unmatched group, the whole expression will fail to match and hence regex.exec('1d10h') will return null.

To get rid of undefined elements just filter them out:

const result = regex.exec('1d10h').filter(x => x);
Sign up to request clarification or add additional context in comments.

3 Comments

you can use the static function Boolean for filtering .filter(Boolean)
ah, I see what you mean - it makes sense when I looked at it a bit more, I'll go ahead and mark this as correct, thanks!
And you could slice off the first element: regex.exec('1d10h')?.filter(Boolean).slice(1) - the optional chaining operator ?. makes it return undefined if the regex did not match, but is not available in all browsers.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.