Expression régulière pour le formatage de numéros en JavaScript

Je dois afficher un numéro formaté sur une page Web en utilisant JavaScript. Je souhaite le formater afin qu'il y ait des virgules dans les bons endroits. Comment ferais-je cela avec une expression régulière? Je suis parvenu à quelque chose comme ça:

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

… et je me suis rendu compte que ce serait plus complexe que je le pense (et que la regex ci-dessus n'est même pas proche de ce dont j'ai besoin). J'ai fait quelques recherches et j'ai du mal à trouver quelque chose qui fonctionne pour cela.

Fondamentalement, je veux ces résultats:

  • 45 devient 45
  • 3856 devient 3 856
  • 398868483992 devient 398 868 483 992

… vous avez l'idée.

    Cela peut se faire en un seul regex, sans itération requise. Si vous n'utilisiez pas JavaScript, vous pouvez simplement utiliser lookaround et simplement insérer des virgules aux bons endroits:

    Recherchez pour (?<=\d)(?=(\d\d\d)+(?!\d)) et remplacez tous par ,

    Mais JavaScript ne prend pas en charge lookbehind, donc ça ne fonctionne pas. Heureusement, il suffit de changer un peu:

    Recherchez (\d)(?=(\d\d\d)+(?!\d)) et remplacez tous par \1,

    Donc, en JavaScript, cela ressemblerait à:

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

    Explication: Faites valoir que, à partir de la position actuelle dans la chaîne, il est possible de faire correspondre les chiffres en multiples de trois et qu'il y a un chiffre à gauche de la position actuelle.

    Cela fonctionnera également avec des décimales (123456.78) tant qu'il n'y aura pas trop de chiffres "à droite du point" (sinon vous obtenez 123,456,789,012).

    Vous pouvez également le définir dans un prototype numéro, comme suit:

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

    Et puis, utilisez-le comme ceci:

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

    Crédit: Jeffrey Friedl, Mastering Regular Expressions, 3ème. Édition , p. 66-67

    Le formatage d'un numéro peut être traité avec élégance avec une seule ligne de code.

    Ce code étend l'objet Numéro; Les exemples d'utilisation sont inclus ci-dessous.

    Code:

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

    Comment ça marche

    L'expression régulière utilise un look-ahead pour trouver des positions dans la chaîne où la seule chose à droite est un ou plusieurs groupes de trois nombres, jusqu'à ce qu'une décimale ou la fin de chaîne soit rencontrée. Le .split() est utilisé pour briser la chaîne à ces points en éléments de tableau, puis le .join() fusionne ces éléments dans une chaîne, séparés par des virgules.

    Le concept de trouver des positions dans la chaîne, plutôt que de faire correspondre les caractères réels, est important pour diviser la chaîne sans enlever les caractères.

    Exemples d'utilisation:

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

    Bien sûr, le code peut facilement être étendu ou modifié pour gérer les considérations locales. Par exemple, voici une nouvelle version du code qui détecte automatiquement les paramètres régionaux et échange l'utilisation de virgules et de périodes.

    Version locale:

     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( "." ); } }; 

    À moins que cela ne soit vraiment nécessaire, je préfère la simplicité de la première version.

    // Vous voudrez peut-être prendre en compte les décimales

     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 () = valeur retournée: (String) 10 000 000 000.34

    Si vous voulez vraiment un regex, vous pouvez utiliser une boucle de deux en un:

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

    Et si vous voulez être chic, vous pouvez également formater des nombres avec des décimales:

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

    Modifier:

    Vous pouvez également le faire avec 2 expressions régulières et aucune boucle, fractionnement, joint, etc.:

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

    Le premier regex met une virgule après les 1 ou 2 premiers chiffres si le nombre restant de chiffres est divisible par trois. La deuxième regex place une virgule après chaque groupe restant de 3 chiffres.

    Ceux-ci ne fonctionneront pas avec des décimales, mais ils fonctionnent bien pour les nombres entiers positifs et négatifs.

    Sortie de test:

     45 3,856 398,868,483,992 635 12,358,717,859,918,856 -1,388,488,184 

    Quelqu'un a mentionné que lookbehind n'est pas possible dans Javascript RegExp. Voici une excellente page qui explique comment utiliser lookaround (lookahead et lookbehind).

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

    Underscore.string a une belle implémentation .

    Je l'ai modifié légèrement pour accepter des chaînes numériques.

     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; }, 

    Essayez quelque chose comme ceci:

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

    Je pense que vous devrez nécessairement faire des passes multiples pour y parvenir avec des expressions régulières. Essayez ce qui suit:

    1. Exécutez un regex pour un chiffre suivi de 3 chiffres.
    2. Si ce regex correspond, remplacez-le par le premier chiffre, puis une virgule, puis les 3 chiffres suivants.
    3. Répétez jusqu'à ce que (1) ne trouve aucune correspondance.

    L'itération n'est pas nécessaire

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

    Résultats

     1 1 45 45 2856 2,856 398868483992 398,868,483,992 

    Commencez par inverser un tableau de caractères, puis ajoutez des virgules après chaque troisième numéro, à moins qu'il ne soit juste avant la fin de la chaîne ou avant un signe. Ensuite, inversez le tableau de caractères à nouveau et devenez une chaîne à nouveau.

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

    Brandon

    Je n'ai pas vu trop de réponses pour travailler le regex à partir de la virgule, alors j'ai pensé que je pourrais entourage.

    Je me demandais s'il y avait un avantage élégant pour réécrire le regexp pour scanner à l'arrière …

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

    >> Fiddle Demo <<

    Cela représente une décimale.