【问题标题】:Number grouping using regexps使用正则表达式进行数字分组
【发布时间】:2009-12-16 10:10:21
【问题描述】:

是否可以使用单程仅正则表达式进行数字分组(例如,将数字1000转换为字符串"1 000")? (我知道在某些系统中,正则表达式和语言设施之间的界限有些模糊 - 在回复之前听听你的良心。)

我问的原因:另一位开发人员最近问我如何在 JavaScript 中进行数字分组,并向我展示了一个使用正则表达式的 JavaScript 函数稍微不正确。我给了他a better alternative,但他的正则表达式对我唠叨,因为这种重写绝对是常规语法应该能够做的事情,但我真的不知道如何为其编写正则表达式。

这是我第一次天真的尝试,我知道这是不正确的:

function group(n) { return n.toString().replace(/(\d{3})/g, "$1 "); }

这种方法有两个缺陷; group(1000) 产生 "100 0"group(100) 产生 "100 "(尾随空格)。你可以这样修复它:

String.prototype.reverse = function () { 
    var a = []; 
    for (var i = this.length; i >= 0; --i) a.push(this[i]); 
    return a.join("");
}; 
function group(n) { 
    return n.toString().reverse().replace(/(\d{3})/g, "$1 ").
        trimRight().reverse(); 
}

但这需要的不是一次,不是两次,甚至不是三次,而是四次传球(两次反转,一次替换和trimRight)!然后我冒险进入后视区,并想出了:

function group(n) { return n.toString().replace(/(\d{3}(?!\d))/g, " $1");

...这根本不起作用(编辑 - 可能是因为我混淆了后视和负前瞻...) - 它只匹配最后三个数字(@987654333 @ 变为 "1000000 000")。前瞻效果更好:

function group(n) { return n.toString().replace(/(\d{3})(?=\d)/g, "$1 "); }

这或多或少让我回到了我开始的地方 - 我摆脱了尾随空格,但group(1000) 仍然产生"100 0"

那么 - 这可以通过单个正则表达式替换传递来完成吗?我与语言无关,因为这应该只需要使用正则表达式工具。

注意:这不是关于如何进行本地化的问题,我也没有进行过早的优化。我只是好奇这是否可能,如果不可能,为什么不呢。

【问题讨论】:

  • 仅供参考,(?!\d) 不是后视,而是负前瞻。
  • @Alan Moore - 天哪!这就解释了为什么它不起作用。 :)
  • 我知道这不是关于如何进行本地化,但如果有人为此而来,请使用Number.toLocaleString

标签: regex language-agnostic


【解决方案1】:

这是一个适用于 JavaScript 的版本:

return n.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1 ");

【讨论】:

    【解决方案2】:

    这是在 Perl 中完成的:

    $num =~ s/(?<=\d)(\d{3})(?=(\d{3})*(\D|$))/ $1/g;
    

    分解:

    • (?&lt;=\d) - 我们正在检查我们的匹配是否前面有一个使用后视的数字

    • (\d{3}) - 我们正在寻找一组三位数字

    • (?= - 我们使用的是前瞻,所以这三个数字后面必须跟一些东西

    • (\d{3})* - 这将匹配 0 组或更多组 3 位数字,即 0、3、6... 位。

    • (\D|$) - 这将匹配非数字或字符串的结尾。

    所以我们要找到一个数字,然后是 3 个数字,然后是 0、3、6... 数字,然后再没有数字。

    不幸的是,JavaScript 在其正则表达式中没有lookbehind,因此这种模式在 JavaScript 中不起作用。如果您放弃向后看,您会在 3、6、9... 位的数字前面放置一个前导空格。

    【讨论】:

      【解决方案3】:
      n.toString().replace(/(\d)(?=(\d{3})+\b)/g,"$1 ")
      

      在每个数字后添加一个空格,后跟 3i 个数字。例如,在123456789 中,将匹配以下数字:26
      工作演示:http://jsbin.com/iruzu

      【讨论】:

      • +1 用于演示,但您将 $1 留在了替换字符串之外。而不是1 00010087 654 321,而是显示0001008 65 321
      • 快速推特确认:这是 jsbin 中的错误。 twitter.com/rem/status/6727791738
      • 不过,这是一个很酷的资源;感谢您引起我的注意。
      猜你喜欢
      • 1970-01-01
      • 2021-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-14
      相关资源
      最近更新 更多