wake-up-neo.net

Regulärer Ausdruck zum Formatieren von Zahlen in JavaScript

Ich muss mit JavaScript eine formatierte Zahl auf einer Webseite anzeigen. Ich möchte es so formatieren, dass es an den richtigen Stellen Kommas gibt. Wie mache ich das mit einem regulären Ausdruck? Ich bin soweit so weit gekommen:

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

... und dann wurde mir klar, dass dies komplexer wäre als ich denke (und der Regex oben ist noch nicht einmal nahe was ich brauche). Ich habe etwas gesucht und es fällt mir schwer, etwas zu finden, das dafür funktioniert.

Grundsätzlich möchte ich diese Ergebnisse:

  • 45 wird 45 
  • 3856 wird 3856
  • 398868483992 wird 398,868,483,992

...Du hast die Idee.

36

Dies kann in einem einzigen regulären Ausdruck erfolgen, es ist keine Iteration erforderlich. Wenn Ihr Browser ECMAScript 2018 unterstützt, können Sie einfach lookaround verwenden und an den richtigen Stellen Kommas einfügen:

Suchen Sie nach (?<=\d)(?=(\d\d\d)+(?!\d)) und ersetzen Sie alle durch ,.

In älteren Versionen unterstützt JavaScript kein LookHind, daher funktioniert es nicht. Zum Glück müssen wir nur ein wenig ändern:

Suchen Sie nach (\d)(?=(\d\d\d)+(?!\d)) und ersetzen Sie alle durch \1,.

In JavaScript würde das so aussehen:

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

Erläuterung: Stellen Sie fest, dass ab der aktuellen Position in der Zeichenfolge Ziffern in Vielfachen von dreien abgeglichen werden können und dass sich links von der aktuellen Position eine Ziffer befindet.

Dies funktioniert auch mit Dezimalzahlen (123456.78), solange es nicht zu viele Ziffern "rechts vom Punkt" gibt (andernfalls erhalten Sie 123.456.789,012).

Sie können es auch wie folgt in einem Number-Prototyp definieren:

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

Und dann so verwenden:

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

Bildnachweis: Jeffrey Friedl, Mastering Regular Expressions, 3. Ausgabe , p. 66-67

106
Tim Pietzcker

Das Formatieren einer Zahl kann elegant mit einer Codezeile erfolgen.

Dieser Code erweitert das Number-Objekt. Verwendungsbeispiele sind unten aufgeführt.

Code:

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

Wie es funktioniert

Der reguläre Ausdruck verwendet einen Look-Ahead, um Positionen innerhalb der Zeichenfolge zu finden, an denen rechts davon nur eine oder mehrere Gruppierungen von drei Zahlen stehen, bis entweder eine Dezimalzahl oder das Ende der Zeichenfolge gefunden wird. Die Funktion .split() wird verwendet, um die Zeichenfolge an diesen Punkten in Array-Elemente zu unterteilen, und die Funktion .join() führt diese Elemente dann durch Kommas getrennt in eine Zeichenfolge zurück.

Das Konzept des Auffindens von positions innerhalb der Zeichenfolge, anstatt tatsächliche Zeichen zu finden, ist wichtig, um die Zeichenfolge zu teilen, ohne Zeichen zu entfernen.

Verwendungsbeispiele:

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

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

Natürlich kann der Code leicht erweitert oder geändert werden, um Überlegungen zum Gebietsschema zu berücksichtigen. Hier ist zum Beispiel eine neue Version des Codes, die die Gebietsschemaeinstellungen automatisch erkennt und die Verwendung von Kommas und Punkten austauscht.

Ländereinstellung:

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

Wenn es nicht wirklich notwendig ist, ziehe ich die Einfachheit der ersten Version vor.

14
Speednet

// Vielleicht möchten Sie Dezimalzahlen berücksichtigen

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 () = Rückgabewert: (String) 10.000.000.000.34

3
kennebec

Wenn Sie wirklich einen Regex wollen, können Sie zwei in einer while-Schleife verwenden:

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

Und wenn Sie Lust haben wollen, können Sie auch Zahlen mit Dezimalstellen formatieren:

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

Bearbeiten:

Sie können dies auch mit 2 regulären Ausdrücken und ohne Schleife, Splits, Joins usw. tun:

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

Der erste reguläre Ausdruck setzt nach den ersten 1 oder 2 Ziffern ein Komma, wenn die verbleibende Anzahl von Ziffern durch drei teilbar ist. Der zweite Regex setzt nach jeder verbleibenden Gruppe von 3 Ziffern ein Komma.

Diese funktionieren nicht mit Dezimalzahlen, aber sie eignen sich hervorragend für positive und negative ganze Zahlen.

Testausgabe:

45
3,856
398,868,483,992

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

Jemand hat erwähnt, dass Lookbehind in Javascript RegExp nicht möglich ist. Hier ist eine großartige Seite, die erklärt, wie Lookaround (Lookahead und Lookbehind) verwendet wird.

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

1
Robusto

underscore.string hat eine nette Implementierung .

Ich habe es leicht geändert, um numerische Zeichenfolgen zu akzeptieren.

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

Iteration ist nicht notwendig

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

Ergebnisse

1
1

45
45

2856
2,856

398868483992
398,868,483,992
0
Justin Johnson

Brandon,

Ich habe nicht zu viele Antworten vom regulären Dezimalpunkt aus gesehen.

Ich fragte mich, ob es einen eleganten Vorteil hat, den Regex umzuschreiben, um ihn von hinten nach vorne zu scannen ...

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

Dies ist für jede Dezimalstelle verantwortlich.

0
Levi Beckman

Versuchen Sie etwas so: 

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

Ich denke, Sie müssten unbedingt mehrere Durchläufe machen, um dies mit regulären Ausdrücken zu erreichen. Versuche Folgendes:

  1. Führen Sie einen Regex für eine Ziffer gefolgt von 3 Ziffern aus.
  2. Wenn dieser reguläre Ausdruck übereinstimmt, ersetzen Sie ihn durch die erste Ziffer, dann ein Komma und dann die nächsten 3 Ziffern.
  3. Wiederholen, bis (1) keine Übereinstimmungen findet.
0
Ryan Brunner

Zuerst müssen Sie ein Zeichenfeld umkehren und dann nach jeder dritten Zahl Kommas hinzufügen, es sei denn, es befindet sich direkt vor dem Ende der Zeichenfolge oder vor dem Zeichen. Kehren Sie dann das Zeichenfeld erneut um und machen Sie es erneut zu einem String.

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