String replace all that not mach regex

Viewed 103

This is my javascript regex: /^(\d+\.?\d{0,2})$/ My target is to replace all inputs according to it. Is that possible? Example:

123a.12 => 123.12
aaa12aa => 12
12.aaa13 => 12.13
12.aaa => 12
12.555 => 12.55
12.... => 12
12.    => 12
12.35.12.14 => 12.35
12.aaa.2.s.5 => 12.25

I was using str.replace(/^(\d+\.?\d{0,2})$/, '') but with no success

4 Answers

Do in in steps: first replace anything that is not number, then trim .:

function getNum(input, expected){
  num = input
    .replace(/[^\d.]/g, '')
    .replace(/\.+$/, '')
    .replace(/^\.+/, '');
    
  console.log(input + ' => ' + num + ' | ' + expected)
}

getNum('123a.12', '123.12');
getNum('aaa12aa', '12');
getNum('12.aaa13', '12.13');
getNum('12.aaa', '12');
getNum('abcd.12', '12');
getNum('abcd.efg.12.abcd.efg', '12');

One option for your current examples is to use an alternation to match either not a digit, dot or whitespace char or match a dot followed by 1+ non digits and assert that is does not end on a digit.

[^\d.\s]+|\.[^\d]+(?!\d)\b

[
  "123a.12",
  "aaa12aa",
  "12.aaa13",
  "12.aaa "
].forEach(str => console.log(str.replace(/[^\d.\s]+|\.[^\d]+(?!\d)\b/g, '')));

Edit after the updated question

To get the values without trailing dots and 2 decimals, you could make use of replace and the callback function.

First replace all not digits and dots with an empty space using [^\d.]+

The use a pattern to get the first dot and 2 following digits. Use capturing groups to return the match that you want by checking the value of the any other group than the first.

^(\d+)(?:\.+|(\.)\.*(\d)\.*(\d).*)$

Regex demo

strings = [
  "123a.12",
  "aaa12aa",
  "12.aaa13",
  "12.aaa",
  "12.555",
  "12....",
  "12.",
  "12.35.12.14",
  "12.aaa.2.s.5"
].map(str => {
  return str
    .replace(/[^\d.]/g, '')
    .replace(/^(\d+)(?:\.+|(\.)\.*(\d)\.*(\d).*)$/, function(m, g1, g2, g3, g4) {
      return undefined !== g2 ? g1 + g2 + g3 + g4 : g1;
    });
});

console.log(strings);

You can replace the first . with a placeholder, I have used |. Then, remove any characters that are not digits or the placeholder. Finally, replace your placeholder with .. Then, remove anything past 2 decimal places:

const num = (s) => {
  const clean = s.replace(".", "|").replace(/[^\d|]/g, '').replace('|', '.');
  
  return parseInt(clean * 100) / 100;
}

const tests = [
  "123a.12",
  "aaa12aa",
  "12.aaa13",
  "12.aaa",
  "12.555",
  "12....",
  "12.",
  "12.35.12.14",
  "12.aaa.2.s.5"
];

tests.forEach(test => console.log(test + " => " + num(test)));

This should handle all cases, unless there are two periods in a row.

let myString = 'test1.0.test'
myStr.replace(/[^\d.-]/g,'').replace(/[^\d.-]|\.$/g, '')
// 1.0
Related