JavaScript:替换除数字以外的所有内容,只允许一个小数点。

3

这适用于整数,例如:

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

以下正则表达式可以实现相同的功能,但只允许一个小数点:

  • ^(\d+\.?\d*)$

示例:

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

10.01.23 应该保留 10.01 还是变成 10.0123? - Christoph Herold
"a1b2c3d.e4f5g6h" 是什么意思? - trincot
10.0123 @ChristophHerold - Tiago Fernandez
123.456 @trincot - Tiago Fernandez
6个回答

17

使用两个替换:

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

第一个操作会删除除数字和点以外的所有字符。

第二个替换匹配数字序列,可能后跟一个点,但有两种不同的方式。当该序列出现在字符串开头时,可选的点被放在第一个捕获组内,而对于所有其他匹配,点位于第二个捕获组之外。

有两个捕获组,但对于任何给定的匹配,只有其中一个会实际包含内容。因此,可以使用$1$2在任一情况下重现捕获的内容。这将包括第一个点,但不包括任何其他点。


2
你可以使用parseFloat并转换回字符串,即可实现。最初的回答中已经提到了这一点。

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

使用正则表达式的一种方法。

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

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


1
不是在点踩,但是所有的代码都没有给出预期的输出。OP想要将“10.01.23”变成“10.0123”,而不是“10.01”。 - Code Maniac

1

更新

为什么不采用老派的方式:

    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]));
    }

只需要对字符串进行一次迭代,因此您可能不会得到更好的运行时间。

旧答案,不起作用

这个也应该可以工作(但它没有,感谢trincot指出):

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]));
}

首先,替换所有非数字和点。然后,捕获第一个点之后的所有内容,并用任何不是点的内容替换它。但是,这需要一个两步正则表达式。

你在第一个测试中丢失了一些数字。当输入有3个或更多点时,问题就会出现。 - trincot
对于旧循环回答+1。 - Code Maniac

1
你可以这样做,需要使用两个replace方法:
  1. 为了除数字和小数点之外的所有内容,请使用否定字符类`[^\d.]。
  2. 为了删除重复的点,使用回调替换需要替换第一个点后面的内容,所以使用\.([.\d]+)$来匹配第一个点后的整个字符串(包括点),并在回调中从捕获的值(第一个点后的字符串)中删除所有剩余的点。

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

演示:

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)}`))


0

如果你想要除了数字以外的所有东西都删除,而且只保留第一个点的出现,那么这将是一个很好而简单的解决方案。

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

输出:12.34

第一次替换:将第一个点(.)替换为波浪号(~)。 第二次替换:仅保留数字和波浪号(只有一个)。 第三次替换:将波浪号替换为点。


0

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, '') 用于替换任何非数字字符和非 . 字符。

[0-9]+ 匹配从0到9的数字,+ 表示匹配一次或多次。

. 后面跟着一个点。

[0-9]*? 匹配从0到9的数字(但可以匹配零次或多次)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接