How to remove all non numeric characters (excluding minus, dot and comma) in a string in Javascript?

Viewed 2591

Numeric characters are

0 1 2 3 4 5 6 7 8 9 dot comma minus at the start of the string

I need to remove all non numeric characters from a string. Here examples

123 -> 123

123.45 -> 123.45

123,45 -> 123,45

-123 -> -123

-123.45 -> -123.45

-123,45 -> -123,45

--123.45 -> -123.45

--123,45 -> -123,45


a -> empty string

-a -> -

a123 -> 123

-a123 -> -123

a123.45 -> 123.45

-a123.45 -> -123.45

a123.b45 -> 123.45

-a123.b45 -> -123.45

123.-34 -> 123.34

-123.-34 -> -123.34

--123.-34 -> -123.34

Here is what I have so far

"123.45abc".replace(/[^0-9.,]/g,""); -> 123.45

but this fails

"-123.45abc".replace(/[^0-9.,]/g,""); -> 123.45

This works

"-123.45abc".replace(/-[^0-9.,]/g,""); -> -123.45

but now this fails

"-123.45-abc".replace(/-[^0-9.,]/g,""); -> -123.45bc

This answer almost solves my problem but minus signs inside the string are not removed.

I am doing this in javascript using regex. Regex is not compulsory.


Update The input will have at most one comma or one dot. 12.34.56.78 will never be input

5 Answers

To remove all chars but digits, commas, dots and a hyphen at the start of the string, you may use

text = text.replace(/^(-)|[^0-9.,]+/g, '$1');

See the regex demo

Details

  • ^(-) - start of string and a - captured into Group 1
  • | - or
  • [^0-9.,]+ - any 1+ chars other than digits, . and ,.

The replacement is $1, i.e. if there was a leading - it will remain in the result.

A bit more comprehensive regex that only keeps the last non-final comma/dot is

text = text.replace(/^(-)|[.,](?=[^.,]*[.,](?!$))|[,.]+$|[^0-9.,]+/g, '$1');

See this regex demo

Here, some more alternatives are added:

  • [.,](?=[^.,]*[.,](?!$)) - matches . or , that are followed with another . or , somewhere after 0+ chars other than . and ,
  • [,.]+$ - matches any 1+ trailing commas/dots.

The way without Regex:

let allowedChars = "01234567890.,-,+";
let input = "-a123.b45";

let result = Array.from(input).filter(f=> allowedChars.includes(f)).join('');
console.log(result);

The way with Regex:

let regex = /[^\d.+-]|\.(?=.*\.)/g;
const subst=``;
const str = '+-1,23.456abc';
const result = str.replace(regex, subst);
console.log(result);
/^-?[^\d,.]/g/

Here we're saying that a match must start with a '-' zero or one times. Afterwards, it can be followed by any sequence of numbers, ',', or '.'

It looks to me though like you're trying to match any and all numbers, which have an optional - sign, and are of the form 123,456,789.000000. This regex will be correct for a number of the form, say, -123....,,,,456,,,78.,.9, which I'm assuming is something you don't want.

An other non-regex suggestion similar to stepUp's answer. This uses the for...of loop (ES6 syntax).

const filterChars = (str, allowed) => {
  let newStr = '';
  for (let letter of str) newStr += allowed.includes(letter) ? letter : '';
  return newStr;
}

const result = filterChars('-23a', '-123456...')

console.log(result) // '-23'

This is a very re-usable solution, what you have to do is to define a function that:

  • returns true if the string is valid
  • returns false if the string contains an invalid pattern

Then we iterate over the string using split and reduce, and let's decide what to accept or to reject, char by char:

const testString = '--123.-34';
const isValid = str => {
   return /^[-]{0,1}\d*(\.|,)?\d*$/.test(str);
};

const cleanString = testString
   .split('')
   .reduce((str, char) => {
     if (isValid(str + char)) {
       return str + char;
     }
     return str;
   }, '');
   
 console.log(cleanString);

The isValid function can be refactored without regular expressions

Related