1

I'm attempting to extract any text characters at the beginning, and the following two numbers of a string. If the string starts with a number, I'd like to get an empty string value instead so the resulting array still contains 3 values.


String: 'M2.55X.45'

Code: 'M2.55X.45'.match(/(^[a-zA-Z]+)|((\.)?\d+[\/\d. ]*|\d)/g)

Expected: ["M", "2.55", ".45"]

Actual (correct): ["M", "2.55", ".45"]


String: '2.55X.45'

Code: '2.55X.45'.match(/(^[a-zA-Z]+)|((\.)?\d+[\/\d. ]*|\d)/g)

Expected: ["", "2.55", ".45"]

Actual: ["2.55", ".45"]

Badger
  • 301
  • 3
  • 15

3 Answers3

3

Use /^([a-zA-Z]?)(\d*(?:\.\d+)?)[a-zA-Z](\d*(?:\.\d+)?)$/.exec("2.55X.45") instead. This returns an array where the 1st element is the entire match, so you must access groups 1-indexed, for example, match[1] for the 1st value. You can try this out here.

SuperStormer
  • 4,997
  • 5
  • 25
  • 35
1

Your current regex uses an alternate clause (|), which creates different types of grouping depending on which alternate is matched.

Here's an example (cleaned up a bit) that creates explicit groups and makes the individual groups optional.

const regex = /^([a-zA-Z]*)?(\d*(?:\.\d+)?)([a-zA-Z]+)(\d*(?:\.\d+)?)$/

console.log(regex.exec("2.55X.45"))
console.log(regex.exec("M2.55X.45"))

Note that I've removed the g flag, so the regex's state isn't preserved.

I've also used exec instead of match to not discard capture groups.

Cameron Little
  • 3,487
  • 23
  • 35
1

You can try this pattern

(\D*)(\d+(?:\.\d+))\D+(\.\d+)

enter image description here

let finder = (str) => {
  return (str.match(/^(\D*)(\d+(?:\.\d+))\D+(\.\d+)/) || []).slice(1)
}

console.log(finder('M2.55X.45'))
console.log(finder("2.55X.45"))
Code Maniac
  • 37,143
  • 5
  • 39
  • 60