You may use
.replace(/.(?=.?$)/g, "<span>$&</span>")
See the regex demo
If these must be digits, replace . with \d:
.replace(/\d(?=\d?$)/g, "<span>$&</span>")
The pattern matches
- \d- a digit
- (?=\d?$)- that is followed with an end of string or a digit and end of string.
The $& is a replacement backreference that references the whole match value from the string replacement pattern.
JS demo:
console.log("-1:23".replace(/.(?=.?$)/g, "<span>$&</span>"));
console.log("-1:23".replace(/\d(?=\d?$)/g, "<span>$&</span>"));
 
 
Now, to make it more dynamic, you may use a limiting (range/interval) quantifier:
function wrap_chars(text, num_chars) {
  var reg = new RegExp(".(?=.{0," + (num_chars-1) + "}$)", "g");
  return text.replace(reg, "<span>$&</span>");
}
console.log(wrap_chars("-1:23", 1)); // wrap one char at the end with span
console.log(wrap_chars("-1:23", 2)); // wrap two chars at the end with span