最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

ecmascript 6 - Javascript: replace everything but numbers and allow only one dot - Stack Overflow

programmeradmin4浏览0评论

This works for integers, e.g.:

'123x'.replace(/\D/g, '')
'123'

Which regular expression would achieve the same, but allowing only one dot? Examples:

  • 1 -> 1
  • 1x -> 1
  • 10. -> 10.
  • 10.0 -> 10.0
  • 10.01 -> 10.01
  • 10.01x -> 10.01
  • 10.01. -> 10.01

This works for integers, e.g.:

'123x'.replace(/\D/g, '')
'123'

Which regular expression would achieve the same, but allowing only one dot? Examples:

  • 1 -> 1
  • 1x -> 1
  • 10. -> 10.
  • 10.0 -> 10.0
  • 10.01 -> 10.01
  • 10.01x -> 10.01
  • 10.01. -> 10.01
Share Improve this question asked Mar 15, 2019 at 19:15 Tiago FernandezTiago Fernandez 1,4733 gold badges19 silver badges36 bronze badges 4
  • What should happen with 10.01.23 => 10.01 or 10.0123? – Christoph Herold Commented Mar 15, 2019 at 19:18
  • What with "a1b2c3d.e4f5g6h"? – trincot Commented Mar 15, 2019 at 19:20
  • 10.0123 @ChristophHerold – Tiago Fernandez Commented Mar 15, 2019 at 19:24
  • 123.456 @trincot – Tiago Fernandez Commented Mar 15, 2019 at 19:25
Add a comment  | 

6 Answers 6

Reset to default 18

With two replaces:

console.log("a12b3.1&23.0a2x".replace(/[^.\d]/g, '')
                             .replace(/^(\d*\.?)|(\d*)\.?/g, "$1$2"));

The first action will remove all characters other than digits and points

The second replacement matches sequences of digits possibly followed by a point, but it does so in two different ways. When such sequence occurs at the start of the string, the optional point is put inside the first capture group, while for all other matches, the point is outside the (second) capture group.

There are two capture groups, but for any given match, only one of them will actually have content. So the captured content can be reproduced in either case with $1$2. This will include the first point, but exclude any other.

You could use parseFloat and convert back to a string.

console.log(parseFloat('10.01.x').toString());

An approach with a regular expression.

function convert(s) {
    return s.match(/^\d+\.?\d*/)[0];
}

console.log(['1', '1x', '10.', '10.0', '10.01', '10.01x', '10.01.'].map(convert));

You can do something like this, need two replace methods:

  1. For removing everything except digit and dot. For that use negated character class `[^\d.].
  2. For removing duplicate dots use replace with callback where we need to replace content after the first dot so use \.([.\d]+)$ to match entire string after first do(including the dot) and within callback remove all the remaining dots from the captured value(string after the first dot).

'123x'.replace(/[^\d.]/g, '').replace(/\.([.\d]+)$/,function(m,m1){
   return '.' + m1.replace(/\./g, '')
})

DEMO :

var arr = ['1', '1x', '10.', '10.0', '10.01', '10.01x', '10.01.', '10.01.23', 'a1b2c3d.e4f5g6h'];

function format(str) {
  return str.replace(/[^\d.]/g, '').replace(/\.([.\d]+)$/, function(m, m1) {
    return '.' + m1.replace(/\./g, '')
  });
}

arr.forEach((v) => console.log(`${v} => ${format(v)}`))

UPDATE

Why not simply do it old school:

    function formatNumber(s) {
        var hadDot = false, result = '';
        for (var i = 0; i < s.length; i++) {
            var c = s[i];
            if (c >= '0' && c <= '9')
              result += c;
            else if (!hadDot && c == '.') {
              hadDot = true;
              result += c;
            }
        }
        return result;
    }
    var inputs = ['10.01.x23.5asd6', '10.', '10', '.12vx12.1f53', '10.10.'];
    for (var i = 0; i < inputs.length; i++) {
      console.log(formatNumber(inputs[i]));
    }

Requires just one iteration of the string, so you probably won't get any better running time.

OLD ANSWER, WON'T WORK

This should also work (but it doesn't, thanks to trincot for pointing it out):

function formatNumber(s) {
    return s.replace(/[^\d\.]/g, '').replace(/\.(([^\.]*)\.)*/g, '.$2');
}
var inputs = ['10.01.x23.5asd6', '10.', '10', '.12vx12.1f53', '10.10.'];
for (var i = 0; i < inputs.length; i++) {
  console.log(formatNumber(inputs[i]));
}

First, replace all non-digits and dots. Then, capture everything after the first dot, and replace it with anything that is not a dot. But, it needs a two step regex.

let arr = ['1', '1x', '10.', '10.0', '10.01', '10.01x', '10.01.', '10.01.23', 'a1b2c3d.e4f5g6h'];

arr.forEach(val => {
	val = val.replace(/[^\d.]/g, '').match(/([0-9]+(\.[0-9]*)?)/);
	if (val) console.log(val[0]);
})

replace(/[^\d.]/g, '') to replace any non-digit character and non . character.

[0-9]+ digits from 0 to 9 will be matched, and + for match one or more time

. followed by a dot.

[0-9]*? matched from 0 to 9 (but match ZERO or more time)

This would be a good and simple solution if you want to trim everything but numbers along with only the first occurrence of the dots.

"ab12..34..c".replace(".", "~").replace(/[^0-9~]/g, "").replace("~", ".")

OUTPUT: 12.34

1s replace: Assigning the first dot (.) to tilde (~). 2nd replace: Keeping only numbers and the tilde (there is only one). 3rd replace: Replacing tilde with dot.

发布评论

评论列表(0)

  1. 暂无评论