1

I have a string which looks like below

Your statistics:
The trend is going up.
The most recent value for x*y on 2018-12-09 is 469.44.
The max was 2896 on 2018-12-08 and min was 23.1 on 2018-12-08.
Additionally, the median is 367.95 and the mode is 23.1.
There is higher margin for error/mistake.

As you can see I got some float and int in the string. I need to replace all those occurences with span tag surrounding those occurrences

Here I managed to do something basic like replacing the instances of float and int with XXX. But the problem is there are occurrences of date too and that screws up the operation. So this is what I do:

var string = "Your statistics:<br>The trend is going up.<br>The most recent value for x*y on  2018-12-09 is 469.44.<br>The max was 2896 on 2018-12-08 and  min was 23.1 on 2018-12-08.<br>Additionally, the median is 367.95 and the mode is 23.1.<br>There is higher margin for error/mistake."

string = string.replace(/\d+/g, "XXX");
console.log(string)

This is what I get:

Your statistics:<br>The trend is going up.<br>The most recent value for x*y on  XXX-XXX-XXX is XXX.XXX.<br>The max was XXX on XXX-XXX-XXX and  min was XXX.XXX on XXX-XXX-XXX.<br>Additionally, the median is XXX.XXX and the mode is XXX.XXX.<br>There is higher margin for error/mistake.

Now what I want is replace all occurrences of float and int with a span tag surrounding them something like 469.44 be replaced with <span>469.44</span>, 2896 be replaced with <span>2896<span>

So final string would become something like:

Your statistics:<br>The trend is going up.<br>The most recent value for x*y on  2018-12-09 is <span>469.44</span>.<br>The max was <span>2896</span> on 2018-12-08 and  min was <span>23.1</span> on 2018-12-08.<br>Additionally, the median is <span>367.95</span> and the mode is <span>23.1</span>.<br>There is higher margin for error/mistake.

How do I accomplish this ensuring dates are not messed up?

Souvik Ray
  • 2,899
  • 5
  • 38
  • 70

3 Answers3

1

This does the job without lookbehind:

var string = "Your statistics:<br>The trend is going up.<br>The most recent value for x*y on  2018-12-09 is -469.44.<br>The max was 2896 on 2018-12-08 and  min was -23.1 on 2018-12-08.<br>Additionally, the median is 367.95 and the mode is 23.1.<br>There is higher margin for error/mistake."

string = string.replace(/(\s)(-?\d+(?:\.\d+)?)([.\s])/g, "$1<span>$2</span>$3");
console.log(string)
Toto
  • 89,455
  • 62
  • 89
  • 125
  • I'm so glad we have SO so we don't have to actually the horrors of regex – alex067 Nov 25 '19 at 19:27
  • @SouvikRay: De rien ;), glad it helps. – Toto Nov 25 '19 at 19:43
  • @Toto Hi friend! I needed a small help. Is there any way negative numbers can be covered too? Like `-124.33`, `-21`, `-0.22` etc. So I want both the minus and the number to be covered. You may post an edit to your answer with your modified regex. – Souvik Ray Nov 26 '19 at 20:41
  • @SouvikRay: Just add `-?` before the first `\d+`, see my edit – Toto Nov 27 '19 at 09:58
1

Another solution without lookbehind.

var string = "Your statistics:<br>The trend is going up.<br>The most recent value for x*y on  2018-12-09 is 469.44.<br>The max was 2896 on 2018-12-08 and  min was 23.1 on 2018-12-08.<br>Additionally, the median is 367.95 and the mode is 23.1.<br>There is higher margin for error/mistake."

let newStr = string.replace(/(\d+[^-]\d+|\s\d\s)(?=[^-0-9])/g,str=>`<span>${str}</span>`)
console.log(newStr)
  • 1
    This will not work for numbers that contain only 1 digit. – Toto Nov 25 '19 at 19:42
  • A serial downvoter was in action, all answers get downvoted! But there is another problem with your regex, it change `blah 12 34 blah` into `blah 12 34 blah` instead of `blah 12 34 blah` – Toto Nov 25 '19 at 19:55
  • 1
    Thanks for the feedback. Anyway I didn't down vote anything. I am here to learn from others and help others. Not to compete with anyone. I don't know how I can prove that, but I know I didn't down vote anything :) . Thanks a lot again for the feedback! – Chathura Widanage Nov 25 '19 at 20:09
  • Forgetting what you just said and back to discussion. This problem doesn't has two consecutive numbers. So I think this should be still valid. – Chathura Widanage Nov 25 '19 at 20:11
  • Don't worry, I'm sure it wasn't you that downvoted. Sometimes people downvote without explanations. – Toto Nov 25 '19 at 21:22
0

/(?<!-\d*)\d+(\.\d+)?(?!\d*-)/g

(?<!something) — negative lookbehind. We don't need to capture the numbers, which have -\d* behind.
   • \d — digit, matches any digit from 0 to 9.
   • * — zero or multiple times

\d+(\.\d+)?\d+ any digit from 1 to multiple times (int numers),
   • (\.\d+)\. dot symbol, \d+ any digits (float numbers),
   • ? — "lazy" match, means "zero or one match"

(?!\d*-) — negative lookahead. We don't need digit with - as well.

let bubu = document.getElementById('bubu');

bubu.innerHTML = bubu.innerHTML
  .replace(/(?<!-\d*)\d+(\.\d+)?(?!\d*-)/g, match => '<span class="red">' + match + '</span>')
.red { color: red; }
<p id="bubu">Your statistics:
The trend is going up.
The most recent value for x*y on 2018-12-09 is 469.44.
The max was 2896 on 2018-12-08 and min was 23.1 on 2018-12-08.
Additionally, the median is 367.95 and the mode is 23.1.
There is higher margin for error/mistake.</p>
OPTIMUS PRIME
  • 1,297
  • 9
  • 20
  • hey do you want to recheck your solution? The code snippet doesn't run and when I try to run it locally in my system, I get this error `'Invalid regular expression: invalid group specifier name`. – Souvik Ray Nov 25 '19 at 19:13
  • https://caniuse.com/#search=lookbehind - it works, but has pure browser support. Now trying to find old version of lookbehind) https://stackoverflow.com/questions/641407/javascript-negative-lookbehind-equivalent maybe... – OPTIMUS PRIME Nov 25 '19 at 19:14