簡體   English   中英

JavaScript 中用於格式化數字的正則表達式

[英]Regular Expression for formatting numbers in JavaScript

我需要使用 JavaScript 在網頁上顯示一個格式化的數字。 我想格式化它,以便在正確的位置有逗號。 我將如何用正則表達式做到這一點? 我已經得到了這樣的東西:

myString = myString.replace(/^(\d{3})*$/g, "${1},");

...然后意識到這會比我想象的更復雜(上面的正則表達式甚至不接近我需要的)。 我已經做了一些搜索,我很難找到適合這個的東西。

基本上,我想要這些結果:

  • 45 變成 45
  • 3856 變成 3,856
  • 398868483992 變成 398,868,483,992

……你懂的。

這可以在單個正則表達式中完成,不需要迭代。 如果您的瀏覽器支持 ECMAScript 2018,您可以簡單地使用環視並在正確的位置插入逗號:

搜索(?<=\\d)(?=(\\d\\d\\d)+(?!\\d))並將所有內容替換為,

在舊版本中,JavaScript 不支持后視,因此不起作用。 幸運的是,我們只需要稍微改變一下:

搜索(\\d)(?=(\\d\\d\\d)+(?!\\d))並將所有替換為\\1,

所以,在 JavaScript 中,這看起來像:

result = subject.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");

說明:斷言從字符串中的當前位置開始,可以匹配三的倍數的數字,並且當前位置還剩一個數字。

只要“點的右邊”沒有太多數字(否則你會得到 123,456.789,012),這也適用於小數 (123456.78)。

您還可以在 Number 原型中定義它,如下所示:

Number.prototype.format = function(){
   return this.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,");
};

然后像這樣使用它:

var num = 1234;
alert(num.format());

圖片來源:Jeffrey Friedl,掌握正則表達式,第 3 期。 ,第 66-67

可以用一行代碼優雅地處理數字格式。

此代碼擴展了 Number 對象; 下面包括使用示例。

代碼:

Number.prototype.format = function () {
    return this.toString().split( /(?=(?:\d{3})+(?:\.|$))/g ).join( "," );
};

怎么運行的

正則表達式使用前瞻來查找字符串中的位置,它的右側唯一的是一個或多個三個數字的分組,直到遇到小數或字符串結尾。 .split()用於將這些點處的字符串分解為數組元素,然后.join()將這些元素合並回一個字符串,以逗號分隔。

在字符串中查找位置而不是匹配實際字符的概念對於拆分字符串而不刪除任何字符很重要。

用法示例:

var n = 9817236578964235;
alert( n.format() );    // Displays "9,817,236,578,964,235"

n = 87345.87;
alert( n.format() );    // Displays "87,345.87"

當然,可以很容易地擴展或更改代碼以處理區域設置問題。 例如,這是一個新版本的代碼,它自動檢測區域設置並交換逗號和句點的使用。

本地化版本:

Number.prototype.format = function () {

    if ((1.1).toLocaleString().indexOf(".") >= 0) {
        return this.toString().split( /(?=(?:\d{3})+(?:\.|$))/g ).join( "," );
    }
    else {
        return this.toString().split( /(?=(?:\d{3})+(?:,|$))/g ).join( "." );
    }
};

除非真的有必要,否則我更喜歡第一個版本的簡單性。

// 您可能需要考慮小數

Number.prototype.commas= function(){
 var s= '', temp, 
 num= this.toString().split('.'), n=num[0];
 while(n.length> 3){
  temp= n.substring(n.length-3);
  s= ','+temp+s;
  n= n.slice(0, -3);
 }
 if(n) s= n+s;
 if(num[1]) s+='.'+num[1];
 return s;
}

var n = 10000000000.34;

n.commas() = 返回值:(字符串)10,000,000,000.34

需要注意的是Intl.NumberFormatNumber.toLocaleString()現在在 JavaScript 中用於此目的:

使用正則表達式的其他答案都分解為十進制數(盡管作者似乎不知道這一點,因為他們只測試了 1 或 2 個小數位)。 這是因為沒有lookbehind,JS正則表達式無法知道您是在處理小數點之前還是之后的數字塊。 這留下了兩種使用 JS 正則表達式解決這個問題的方法:

  1. 知道數字中是否有小數點,並根據它使用不同的正則表達式:

    • /(\\d)(?=(\\d{3})+$)/g對於整數
    • /(\\d)(?=(\\d{3})+\\.)/g表示小數
  2. 使用兩個正則表達式,一個匹配小數部分,第二個對其進行替換。

 function format(num) { return num.toString().replace(/^[+-]?\\d+/, function(int) { return int.replace(/(\\d)(?=(\\d{3})+$)/g, '$1,'); }); } console.log(format(332432432)) console.log(format(332432432.3432432)) console.log(format(-332432432)) console.log(format(1E6)) console.log(format(1E-6))

function numberWithCommas(x) {
    return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
var num=numberWithCommas(2000000); //any number
console.log(num);

enter code here

試試這個

underscore.string一個很好的實現

我稍微修改了它以接受數字字符串。

 function numberFormat(number, dec, dsep, tsep) { if (isNaN(number) || number == null) return ''; number = parseFloat(number).toFixed(~~dec); tsep = typeof tsep == 'string' ? tsep : ','; var parts = number.split('.'), fnums = parts[0], decimals = parts[1] ? (dsep || '.') + parts[1] : ''; return fnums.replace(/(\\d)(?=(?:\\d{3})+$)/g, '$1' + tsep) + decimals; } console.log(numberFormat(123456789)) console.log(numberFormat(123456789.123456789)) console.log(numberFormat(-123456789)) console.log(numberFormat(1E6)) console.log(numberFormat(1E-6)) console.log('---') console.log(numberFormat(123456789, 6, ',', '_')) console.log(numberFormat(123456789.123456789, 6, ',', '_')) console.log(numberFormat(-123456789, 6, ',', '_')) console.log(numberFormat(1E6, 6, ',', '_')) console.log(numberFormat(1E-6, 6, ',', '_'))

嘗試這樣的事情:

function add_commas(numStr)
{
    numStr += '';
    var x = numStr.split('.');
    var x1 = x[0];
    var x2 = x.length > 1 ? '.' + x[1] : '';
    var rgx = /(\d+)(\d{3})/;
    while (rgx.test(x1)) {
        x1 = x1.replace(rgx, '$1' + ',' + '$2');
    }
    return x1 + x2;
}

如果你真的想要一個正則表達式,你可以在一個 while 循環中使用兩個:

while(num.match(/\d{4}/)) {
    num = num.replace(/(\d{3})(,\d|$)/, ',$1$2');
}

如果你想花哨,你也可以用小數點格式化數字:

while(num.match(/\d{4}(\,|\.)/)) {
    num = num.replace(/(\d{3})(,\d|$|\.)/, ',$1$2');
}

編輯:

您還可以使用 2 個正則表達式執行此操作,並且沒有循環、拆分、連接等:

num = num.replace(/(\d{1,2}?)((\d{3})+)$/, "$1,$2");
num = num.replace(/(\d{3})(?=\d)/g, "$1,");

如果剩余的位數可以被 3 整除,則第一個正則表達式會在前 1 或 2 位數字后放置一個逗號。 第二個正則表達式在剩余的每組 3 位數字后放置一個逗號。

這些不適用於小數,但它們適用於正整數和負整數。

測試輸出:

45
3,856
398,868,483,992

635
12,358,717,859,918,856
-1,388,488,184

有人提到在 Javascript RegExp 中不可能進行后視。 這是一個很棒的頁面,解釋了如何使用環視(前瞻和后視)。

http://www.regular-expressions.info/lookaround.html

整數和小數的一個 RegExp:

// Formats number 1234.5678 into string "1 234.5678".
function formatNumber(number: number): string {
    return number.toString().replace(/(?<!(\.\d*|^.{0}))(?=(\d{3})+(?!\d))/g, ' ');
}

console.log(formatNumber(1234.5678)); // "1 234.5678"
console.log(formatNumber(123)); // "123"
console.log(formatNumber(123.45678)); // "123.45678"
console.log(formatNumber(123456789.11111111)); // "123 456 789.1111111"

我認為您必須進行多次傳遞才能使用正則表達式實現這一點。 請嘗試以下操作:

  1. 運行一位數字后跟 3 位數字的正則表達式。
  2. 如果該正則表達式匹配,則將其替換為第一位數字,然后是逗號,然后是接下來的 3 位數字。
  3. 重復直到 (1) 找不到匹配項。

首先反轉一個字符數組,然后在每三個數字后添加逗號,除非它就在字符串末尾或 - 符號之前。 然后再次反轉字符數組並再次使其成為字符串。

function add_commas(numStr){
    return numStr.split('').reverse().join('').replace(/(\d{3})(?=[^$|^-])/g, "$1,").split('').reverse().join('');
}

迭代不是必需的

function formatNumber(n, separator) {
    separator = separator || ",";

    n = n.toString()
        .split("").reverse().join("")
        .replace(/(\d{3})/g, "$1" + separator)
        .split("").reverse().join("");

    // Strings that have a length that is a multiple of 3 will have a leading separator
    return n[0] == separator ? n.substr(1) : n;
}

var testCases = [1, 45, 2856, 398868483992];
for ( var i in testCases ) {
    if ( !ns.hasOwnProperty(i) ) { continue; }
    console.info(testCases[i]);   
    console.log(formatNumber(testCases[i]));
}

結果

1
1

45
45

2856
2,856

398868483992
398,868,483,992

布蘭登,

我沒有看到太多從小數點開始使用正則表達式的答案,所以我想我可能會插話。

我想知道重寫正則表達式以從后向前掃描是否有任何優雅的好處......

function addCommas(inputText) {
    // pattern works from right to left
    var commaPattern = /(\d+)(\d{3})(\.\d*)*$/;
    var callback = function (match, p1, p2, p3) {
        return p1.replace(commaPattern, callback) + ',' + p2 + (p3 || '');
    };
    return inputText.replace(commaPattern, callback);
}

>> 小提琴演示 <<

這占任何小數位。

經過這么多搜索,我生成了一個接受所有格式的正則表達式

(\\d+[-, ,(]{0,3}\\d+[-, ,(,)]{0,3}\\d+[-, ,(,)]{0,3}\\d+[)]{ 0,2})

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM