Trevor Reimer
Trevor Reimer

Reputation: 304

Regex sometimes returning null in Javascript

While using regex to match values inside of a formula string I found this issue that regex would return null even though there is a match.

var formula = "round((DATAtotal_sq_ft * .6) + (QTY16 * 4) + (QTY17 * 2) + QTY18 + QTY15 + QTY12 * 18 / 3000, 1)";

const qtyRegex = /(QTY)(\d*)|(LEN)(\d*)|(DATA)([a-zA-Z_-|\d]*)/gm;
let m;

while ((m = qtyRegex.exec(formula)) !== null) {
  var val = 0; // Here is irrelevant code that gets the value
  formula = formula.replace(m[0], val);
}
console.log(formula);

In the above snippet you can see the result that a couple of the values don't get replaced but at the same time all of them get detected by regex101 https://regex101.com/r/WTpvFq/1. For some reason I cant seem to narrow down what I'm doing wrong even after reading a number of different answers to similar problems.

I could use a workaround and use formula.match(qtyRegex) but I am really certain it's just an error in the Regex so I'd prefer properly fixing it instead of plastering it with a patch.

Upvotes: 1

Views: 341

Answers (2)

GMaiolo
GMaiolo

Reputation: 4628

Instead of a while loop you can directly replace using the RegExp with the replacer callback of String.replace like this:

formula = formula.replace(qtyRegex, replacer)

// take a look at the docs I've linked above for an explanation of these params
function replacer(match, p1, p2, ..., offset, string) {
  let calculatedValue = 0 // perform your irrelevant code that gets the value here
  return calculatedValue
}

Upvotes: 1

Barmar
Barmar

Reputation: 782488

When you use the g modifier in a regexp, it remembers the position in the string where it last matched, and subsequent matches start from that position. But your code is replacing the match with a shorter string, so the remembered position may be past the beginning of the next match, and it doesn't find it.

Get rid of the g modifier and it will search from the beginning each time.

var formula = "round((DATAtotal_sq_ft * .6) + (QTY16 * 4) + (QTY17 * 2) + QTY18 + QTY15 + QTY12 * 18 / 3000, 1)";

const qtyRegex = /(QTY)(\d*)|(LEN)(\d*)|(DATA)([a-zA-Z_-|\d]*)/m;
let m;

while ((m = qtyRegex.exec(formula)) !== null) {
  var val = 0; // Here is irrelevant code that gets the value
  formula = formula.replace(m[0], val);
}
console.log(formula);

Upvotes: 1

Related Questions