Frage

Ich bin auf der Suche für eine gute JavaScript-äquivalent der C/PHP printf() oder für C# - /Java-Programmierer, String.Format() (IFormatProvider für .NET).

Meine Voraussetzung ist ein thousand separator-format für zahlen, für jetzt, sondern etwas, Griffe viele Kombinationen (einschließlich Datumsangaben) wäre gut.

Ich merke Microsoft Ajax die Bibliothek bietet eine version der String.Format(), aber wir wollen nicht den ganzen Aufwand, der Rahmen.

War es hilfreich?

Lösung

Von ES6 auf Sie Template Strings verwenden:

let soMany = 10;
console.log(`This is ${soMany} times easier!`);
// "This is 10 times easier!

Siehe Kims für Details unten beantworten .


Ansonsten:

Versuchen Sie sprintf () für JavaScript .


Wenn Sie wirklich wollen ein einfaches Format Verfahren auf eigene Faust zu tun, die Ersetzungen nacheinander nicht tun, aber tun sie gleichzeitig.

Da die meisten der anderen Vorschläge, die erwähnt werden fehlschlagen, wenn ein Ersatz-String früheren Austausches ist auch eine Format-Sequenz wie folgt enthalten:

"{0}{1}".format("{1}", "{0}")

Normalerweise würde erwarten, dass Sie die Ausgabe {1}{0} werden, aber die tatsächliche Ausgabe ist {1}{1}. So tut, um einen gleichzeitig Ersatz statt wie in fearphage Vorschlag .

Andere Tipps

Aufbauend auf den bisher vorgeschlagenen Lösungen:

// First, checks if it isn't implemented yet.
if (!String.prototype.format) {
  String.prototype.format = function() {
    var args = arguments;
    return this.replace(/{(\d+)}/g, function(match, number) { 
      return typeof args[number] != 'undefined'
        ? args[number]
        : match
      ;
    });
  };
}

"{0} is dead, but {1} is alive! {0} {2}".format("ASP", "ASP.NET")

Ausgänge

  

ASP ist tot, aber ASP.NET ist lebendig! ASP {2}


Wenn Sie es vorziehen, nicht String Prototyp zu ändern:

if (!String.format) {
  String.format = function(format) {
    var args = Array.prototype.slice.call(arguments, 1);
    return format.replace(/{(\d+)}/g, function(match, number) { 
      return typeof args[number] != 'undefined'
        ? args[number] 
        : match
      ;
    });
  };
}

Gibt Ihnen das viel vertrauter:

String.format('{0} is dead, but {1} is alive! {0} {2}', 'ASP', 'ASP.NET');

mit dem gleichen Ergebnis:

  

ASP ist tot, aber ASP.NET ist lebendig! ASP {2}

Es ist lustig, weil Stack-Überlauf tatsächlich ihre eigene Formatierungsfunktion für den String Prototyp namens formatUnicorn hat. Versuch es! Gehen Sie in die Konsole und geben Sie so etwas wie:

"Hello, {name}, are you feeling {adjective}?".formatUnicorn({name:"Gabriel", adjective: "OK"});

Firebug

Sie erhalten diese Ausgabe:

Hello, Gabriel, are you feeling OK?

Sie können mit Objekten, Arrays und Zeichenfolgen als Argumente! Ich habe seinen Code und überarbeitete es eine neue Version von String.prototype.format zu produzieren:

String.prototype.formatUnicorn = String.prototype.formatUnicorn ||
function () {
    "use strict";
    var str = this.toString();
    if (arguments.length) {
        var t = typeof arguments[0];
        var key;
        var args = ("string" === t || "number" === t) ?
            Array.prototype.slice.call(arguments)
            : arguments[0];

        for (key in args) {
            str = str.replace(new RegExp("\\{" + key + "\\}", "gi"), args[key]);
        }
    }

    return str;
};

die clevere Array.prototype.slice.call(arguments) Anruf Hinweis - das heißt, wenn Sie in Argumente werfen, die Strings oder Zahlen sind, kein einziges JSON-Style-Objekt, Sie C # 's String.Format Verhalten fast genau.

"a{0}bcd{1}ef".formatUnicorn("foo", "bar"); // yields "aFOObcdBARef"

Das ist, weil Array die slice zwingen wird, was zu einem arguments in Array ist, ob es ursprünglich war oder nicht, und die key wird der Index (0, 1, 2 ...) jedes Array-Elements in einen String umgewandelt werden (zB "0", so "\\{0\\}" für Ihr erstes regexp Muster).

Ordentlich.

Zahlenformatierung in JavaScript

ich auf diese Frage Seite bekam die Hoffnung zu finden, wie man Format Zahlen in JavaScript, ohne eine andere Bibliothek Einführung noch. Hier ist, was ich gefunden habe:

Rounding Gleitkommazahlen

Das Äquivalent von sprintf("%.2f", num) in JavaScript scheint num.toFixed(2) zu werden, die num auf 2 Dezimalstellen formatiert, mit Rundung (aber @ ars265 Kommentar über Math.round siehe unten).

(12.345).toFixed(2); // returns "12.35" (rounding!)
(12.3).toFixed(2); // returns "12.30" (zero padding)

Exponential Form

Das Äquivalent von sprintf("%.2e", num) ist num.toExponential(2).

(33333).toExponential(2); // "3.33e+4"

Hexadezimal und andere Basen

Um Zahlen in der Basis B zu drucken, versuchen num.toString(B). JavaScript unterstützt die automatische Umwandlung zu und von 2 bis 36 Basen (Zusätzlich haben einige Browser Schnell Tutorial auf JS Zahlenformatierung

Mozilla Referenzseite für toFixed () (mit Links zu toPrecision (), toExponential (), toLocaleString (), ...)

Von ES6 auf, die Sie nutzen könnten template-strings:

let soMany = 10;
console.log(`This is ${soMany} times easier!`);
// "This is 10 times easier!

Beachten Sie, dass die template-strings sind umgeben von backticks "anstelle von (Einzel -) quotes.

Für weitere Informationen:

https://developers.google.com/web/updates/2015/01/ES6-Template-Strings

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/template_strings

Hinweis:Überprüfen Sie die mozilla-Website finden Sie eine Liste von unterstützten Browser.

jsxt, Zippo

Diese Option passt besser.

String.prototype.format = function() {
    var formatted = this;
    for (var i = 0; i < arguments.length; i++) {
        var regexp = new RegExp('\\{'+i+'\\}', 'gi');
        formatted = formatted.replace(regexp, arguments[i]);
    }
    return formatted;
};

Mit dieser Option kann ich Strings wie diese ersetzen:

'The {0} is dead. Don\'t code {0}. Code {1} that is open source!'.format('ASP', 'PHP');

Mit Ihrem Code der zweiten {0} nicht ersetzt werden. ;)

Ich benutze diese einfache Funktion:

String.prototype.format = function() {
    var formatted = this;
    for( var arg in arguments ) {
        formatted = formatted.replace("{" + arg + "}", arguments[arg]);
    }
    return formatted;
};

Das ist sehr ähnlich string.format:

"{0} is dead, but {1} is alive!".format("ASP", "ASP.NET")

Node.js Benutzer gibt es util.format , die hat printf-ähnliche Funktionalität:

util.format("%s world", "Hello")

Hier ist eine minimal Implementierung von sprintf in JavaScript: es nur, dass "% s" und "% d", aber ich habe Platz gelassen für sie erweitert werden. Es ist sinnlos, auf die OP, aber auch andere Menschen, die über diesen Thread stolpern von Google kommen könnten davon profitieren.

function sprintf() {
    var args = arguments,
    string = args[0],
    i = 1;
    return string.replace(/%((%)|s|d)/g, function (m) {
        // m is the matched format, e.g. %s, %d
        var val = null;
        if (m[2]) {
            val = m[2];
        } else {
            val = args[i];
            // A switch statement so that the formatter can be extended. Default is %s
            switch (m) {
                case '%d':
                    val = parseFloat(val);
                    if (isNaN(val)) {
                        val = 0;
                    }
                    break;
            }
            i++;
        }
        return val;
    });
}

Beispiel:

alert(sprintf('Latitude: %s, Longitude: %s, Count: %d', 41.847, -87.661, 'two'));
// Expected output: Latitude: 41.847, Longitude: -87.661, Count: 0

Im Gegensatz zu ähnlichen Lösungen in früheren Antworten, dies tut alle Ersetzungen in einem Rutsch , so dass es nicht Teile vorher ersetzt Werte ersetzen wird.

Ich bin niemand überrascht verwendet reduce , dies ist eine native prägnant und leistungsfähige JavaScript-Funktion.

ES6 (EcmaScript2015)

String.prototype.format = function() {
  return [...arguments].reduce((p,c) => p.replace(/%s/,c), this);
};

console.log('Is that a %s or a %s?... No, it\'s %s!'.format('plane', 'bird', 'SOman'));

function interpolate(theString, argumentArray) {
    var regex = /%s/;
    var _r=function(p,c){return p.replace(regex,c);}
    return argumentArray.reduce(_r, theString);
}

interpolate("%s, %s and %s", ["Me", "myself", "I"]); // "Me, myself and I"

Wie es funktioniert:

  

reduzieren wendet eine Funktion gegen einen Akkumulator und jedes Element in der Anordnung (von links nach rechts), um einen einzigen Wert zu reduzieren.

var _r= function(p,c){return p.replace(/%s/,c)};

console.log(
  ["a", "b", "c"].reduce(_r, "[%s], [%s] and [%s]") + '\n',
  [1, 2, 3].reduce(_r, "%s+%s=%s") + '\n',
  ["cool", 1337, "stuff"].reduce(_r, "%s %s %s")
);

JavaScript-Programmierer kann String.prototype.sprintf verwenden unter https: //github.com/ildar-shaimordanov/jsxt/blob/master/js/String.js . Im Folgenden finden Beispiel:

var d = new Date();
var dateStr = '%02d:%02d:%02d'.sprintf(
    d.getHours(), 
    d.getMinutes(), 
    d.getSeconds());

1 Zippo mit der Ausnahme, dass der Funktionskörper muss, wie unten sein oder sonst hängt es die aktuelle Zeichenfolge bei jeder Iteration:

String.prototype.format = function() {
    var formatted = this;
    for (var arg in arguments) {
        formatted = formatted.replace("{" + arg + "}", arguments[arg]);
    }
    return formatted;
};

Zusätzlich zu zippoxer Antwort, verwende ich diese Funktion:

String.prototype.format = function () {
    var a = this, b;
    for (b in arguments) {
        a = a.replace(/%[a-z]/, arguments[b]);
    }
    return a; // Make chainable
};

var s = 'Hello %s The magic number is %d.';
s.format('world!', 12); // Hello World! The magic number is 12.

Ich habe auch eine Nicht-Prototyp-Version, die ich für seine Java-ähnliche Syntax häufiger verwenden:

function format() {
    var a, b, c;
    a = arguments[0];
    b = [];
    for(c = 1; c < arguments.length; c++){
        b.push(arguments[c]);
    }
    for (c in b) {
        a = a.replace(/%[a-z]/, b[c]);
    }
    return a;
}
format('%d ducks, 55 %s', 12, 'cats'); // 12 ducks, 55 cats

ES 2015 update

Die ganze coole neue Sachen in ES 2015 macht viel einfacher diese:

function format(fmt, ...args){
    return fmt
        .split("%%")
        .reduce((aggregate, chunk, i) =>
            aggregate + chunk + (args[i] || ""), "");
}

format("Hello %%! I ate %% apples today.", "World", 44);
// "Hello World, I ate 44 apples today."

Ich dachte, da diese, wie die älteren, nicht wirklich die Buchstaben analysieren, es könnte auch nur ein einziges Token %% verwenden. Dies hat den Vorteil, dass sie offensichtlich und nicht was es schwierig macht einen einzigen % zu verwenden. Wenn Sie jedoch %% aus irgendeinem Grund benötigen, müssten Sie es mit sich selbst ersetzt werden:

format("I love percentage signs! %%", "%%");
// "I love percentage signs! %%"

Ich werde meine eigenen Entdeckungen hinzufügen, die ich gefunden habe, da ich gefragt:

Leider scheint es sprintf nicht Tausendertrennzeichen nicht behandeln wie String-Format .NET Formatierung.

Ich verwende eine kleine Bibliothek namens String.format für JavaScript , die den größten Teil des Format unterstützt String-Funktionen (einschließlich Format von Zahlen und Daten) und verwenden die .NET-Syntax. Das Skript selbst ist kleiner als 4 kB, so dass es nicht viel Aufwand erstellen.

Sehr elegant:

String.prototype.format = function (){
    var args = arguments;
    return this.replace(/\{\{|\}\}|\{(\d+)\}/g, function (curlyBrack, index) {
        return ((curlyBrack == "{{") ? "{" : ((curlyBrack == "}}") ? "}" : args[index]));
    });
};

// Usage:
"{0}{1}".format("{1}", "{0}")

Kredit geht auf (gestrichelte Verbindung) https://gist.github.com/0i0/1519811

Ich möchte meine Lösung für das ‚Problem‘ teilen. Ich habe nicht das Rad neu erfunden, sondern versucht, eine Lösung zu finden, basiert auf, was JavaScript bereits der Fall ist. Der Vorteil ist, dass Sie alle impliziten Konvertierungen kostenlos. Einstellen der Eigenschaft prototype $ von String gibt eine sehr schöne und kompakte Syntax (siehe Beispiele unten). Es ist vielleicht nicht die effizienteste Art und Weise, aber in den meisten Fällen mit einer Leistung handelt es muss nicht Super optimiert werden.

String.form = function(str, arr) {
    var i = -1;
    function callback(exp, p0, p1, p2, p3, p4) {
        if (exp=='%%') return '%';
        if (arr[++i]===undefined) return undefined;
        exp  = p2 ? parseInt(p2.substr(1)) : undefined;
        var base = p3 ? parseInt(p3.substr(1)) : undefined;
        var val;
        switch (p4) {
            case 's': val = arr[i]; break;
            case 'c': val = arr[i][0]; break;
            case 'f': val = parseFloat(arr[i]).toFixed(exp); break;
            case 'p': val = parseFloat(arr[i]).toPrecision(exp); break;
            case 'e': val = parseFloat(arr[i]).toExponential(exp); break;
            case 'x': val = parseInt(arr[i]).toString(base?base:16); break;
            case 'd': val = parseFloat(parseInt(arr[i], base?base:10).toPrecision(exp)).toFixed(0); break;
        }
        val = typeof(val)=='object' ? JSON.stringify(val) : val.toString(base);
        var sz = parseInt(p1); /* padding size */
        var ch = p1 && p1[0]=='0' ? '0' : ' '; /* isnull? */
        while (val.length<sz) val = p0 !== undefined ? val+ch : ch+val; /* isminus? */
       return val;
    }
    var regex = /%(-)?(0?[0-9]+)?([.][0-9]+)?([#][0-9]+)?([scfpexd%])/g;
    return str.replace(regex, callback);
}

String.prototype.$ = function() {
    return String.form(this, Array.prototype.slice.call(arguments));
}

Hier sind einige Beispiele:

String.format("%s %s", [ "This is a string", 11 ])
console.log("%s %s".$("This is a string", 11))
var arr = [ "12.3", 13.6 ]; console.log("Array: %s".$(arr));
var obj = { test:"test", id:12 }; console.log("Object: %s".$(obj));
console.log("%c", "Test");
console.log("%5d".$(12)); // '   12'
console.log("%05d".$(12)); // '00012'
console.log("%-5d".$(12)); // '12   '
console.log("%5.2d".$(123)); // '  120'
console.log("%5.2f".$(1.1)); // ' 1.10'
console.log("%10.2e".$(1.1)); // '   1.10e+0'
console.log("%5.3p".$(1.12345)); // ' 1.12'
console.log("%5x".$(45054)); // ' affe'
console.log("%20#2x".$("45054")); // '    1010111111111110'
console.log("%6#2d".$("111")); // '     7'
console.log("%6#16d".$("affe")); // ' 45054'

Wenn Sie schauen, um die Tausender-Trennzeichen zu behandeln, sollten Sie wirklich verwenden toLocaleString () aus der JavaScript Nummer Klasse, da es die String-Format für die Region des Benutzers.

Der JavaScript Datum Klasse können lokale Daten und Zeiten formatiert werden.

Ich habe eine Lösung sehr nahe an Peters, aber es beschäftigt sich mit Anzahl und Objekt Fall.

if (!String.prototype.format) {
  String.prototype.format = function() {
    var args;
    args = arguments;
    if (args.length === 1 && args[0] !== null && typeof args[0] === 'object') {
      args = args[0];
    }
    return this.replace(/{([^}]*)}/g, function(match, key) {
      return (typeof args[key] !== "undefined" ? args[key] : match);
    });
  };
}

Vielleicht könnte es noch besser sein, mit dem allen deeps Fällen zu behandeln, aber für meine Bedürfnisse ist dies nur in Ordnung.

"This is an example from {name}".format({name:"Blaine"});
"This is an example from {0}".format("Blaine");

PS: Diese Funktion ist sehr cool, wenn Sie mit Übersetzungen in Vorlagen Frameworks wie AngularJS :

<h1> {{('hello-message'|translate).format(user)}} <h1>
<h1> {{('hello-by-name'|translate).format( user ? user.name : 'You' )}} <h1>

Wenn die en.json so etwas wie

ist
{
    "hello-message": "Hello {name}, welcome.",
    "hello-by-name": "Hello {0}, welcome."
}

Das PHPJS Projekt für viele von PHP-Funktionen JavaScript-Implementierungen geschrieben hat. Seit PHP ist sprintf() Funktion im Grunde das gleiche wie C des printf(), ihre JavaScript-Implementierung davon sollte Ihre Bedürfnisse befriedigen.

Ich benutze diese:

String.prototype.format = function() {
    var newStr = this, i = 0;
    while (/%s/.test(newStr))
        newStr = newStr.replace("%s", arguments[i++])

    return newStr;
}

Dann nenne ich es:

"<h1>%s</h1><p>%s</p>".format("Header", "Just a test!");

Eine sehr etwas andere Version, die ich bevorzuge (dies verwendet {xxx} Token anstatt {0} nummerierte Argumente, das ist viel mehr selbsterklärend und Anzüge Lokalisierung viel besser):

String.prototype.format = function(tokens) {
  var formatted = this;
  for (var token in tokens)
    if (tokens.hasOwnProperty(token))
      formatted = formatted.replace(RegExp("{" + token + "}", "g"), tokens[token]);
  return formatted;
};

Eine Variante wäre:

  var formatted = l(this);

, die eine l () Lokalisierungsfunktion fordert zuerst.

Es ist "sprintf" für JavaScript, die Sie unter http: //www.webtoolkit .info / javascript-sprintf.html .

Ich habe einen etwas längeren Formatierer für JavaScript DateJS ) wird es verwenden das.

Beispiele ...

var input = "numbered args ({0}-{1}-{2}-{3})";
console.log(String.format(input, "first", 2, new Date()));
//Outputs "numbered args (first-2-Thu May 31 2012...Time)-{3})"

console.log(input.format("first", 2, new Date()));
//Outputs "numbered args(first-2-Thu May 31 2012...Time)-{3})"

console.log(input.format(
    "object properties ({first}-{second}-{third:yyyy-MM-dd}-{fourth})"
    ,{
        'first':'first'
        ,'second':2
        ,'third':new Date() //assumes Date.prototype.format method
    }
));
//Outputs "object properties (first-2-2012-05-31-{3})"

Ich habe auch mit .asFormat und habe einige Erkennung statt, falls es bereits string.format (wie mit MS Ajax Toolkit (ich hasse diese Bibliothek).

aliased

Für den Fall, jemand eine Funktion globalen Bereich zu verhindern, muss umweltfreundlich, hier ist die Funktion, tut das gleiche:

  function _format (str, arr) {
    return str.replace(/{(\d+)}/g, function (match, number) {
      return typeof arr[number] != 'undefined' ? arr[number] : match;
    });
  };

Für grundlegende Formatierung:

var template = jQuery.validator.format("{0} is not a valid value");
var result = template("abc");

Ich habe die String.format Variante nicht:

String.format = function (string) {
    var args = Array.prototype.slice.call(arguments, 1, arguments.length);
    return string.replace(/{(\d+)}/g, function (match, number) {
        return typeof args[number] != "undefined" ? args[number] : match;
    });
};

Für die Verwendung mit jQuery.ajax () Erfolg Funktionen. Führen Sie nur ein einziges Argument und String ersetzen mit den Eigenschaften dieses Objekts als {} Eigenschaftsname:

String.prototype.format = function () {
    var formatted = this;
    for (var prop in arguments[0]) {
        var regexp = new RegExp('\\{' + prop + '\\}', 'gi');
        formatted = formatted.replace(regexp, arguments[0][prop]);
    }
    return formatted;
};

Beispiel:

var userInfo = ("Email: {Email} - Phone: {Phone}").format({ Email: "someone@somewhere.com", Phone: "123-123-1234" });

Mit sprintf.js statt - man kann ein nettes kleines Format-Dingen macht

String.prototype.format = function(){
    var _args = arguments 
    Array.prototype.unshift.apply(_args,[this])
    return sprintf.apply(undefined,_args)
}   
// this gives you:
"{%1$s}{%2$s}".format("1", "0")
// {1}{0}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top