JavaScript équivalent à printf / String.Format
je cherche un bon équivalent JavaScript du C/PHP printf()
ou pour les programmeurs C#/Java, String.Format()
( IFormatProvider
pour .NET).
mon exigence de base est un format de séparateur de mille pour les nombres pour le moment, mais quelque chose qui gère beaucoup de combinaisons (y compris les dates) serait bon.
je me rends compte que la bibliothèque de Microsoft Ajax fournit une version de String.Format()
, mais nous ne voulons pas de la totalité les frais généraux du cadre de référence.
30 réponses
modifier: à partir de ES6 sur vous pourriez utiliser des chaînes de template:
let soMany = 10;
console.log(`This is ${soMany} times easier!`);
// "This is 10 times easier!
Voir Kim réponse ci-dessous pour plus de détails.
réponse originale:
Essayer sprintf() de JavaScript .
mettre à jour Ok, si vous voulez vraiment faire une méthode de format simple sur votre propre, ne pas faire les remplacements successivement mais ne simultanément.
parce que la plupart des autres propositions qui sont mentionnées échouent quand une chaîne de remplacement du remplacement précédent contient aussi une séquence de format comme ceci:
"{0}{1}".format("{1}", "{0}")
normalement, vous vous attendez à ce que la sortie soit {1}{0}
mais la sortie réelle est {1}{1}
. Alors faites un remplacement simultané à la place comme dans la suggestion de fearphage .
S'appuyant sur les solutions proposées précédemment:
// 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")
sorties
ASP est mort, mais ASP.NET est vivant! ASP {2}
Si vous préférez ne pas modifier String
prototype:
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
;
});
};
}
vous donne beaucoup plus familier:
String.format('{0} is dead, but {1} is alive! {0} {2}', 'ASP', 'ASP.NET');
avec le même résultat:
ASP est mort, mais ASP.NET est vivant! ASP {2}
c'est drôle parce que Stack Overflow a en fait sa propre fonction de formatage pour le prototype String
appelé formatUnicorn
. L'essayer! Allez dans la console et tapez quelque chose comme:
"Hello, {name}, are you feeling {adjective}?".formatUnicorn({name:"Gabriel", adjective: "OK"});
vous obtenez ce résultat:
Hello, Gabriel, are you feeling OK?
vous pouvez utiliser des objets, des tableaux et des chaînes comme arguments! J'ai eu son code et retravaillé pour produire une nouvelle version de String.prototype.format
:
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;
};
notez l'appel intelligent Array.prototype.slice.call(arguments)
-- cela signifie que si vous lancez des arguments qui sont des chaînes ou des nombres, pas un seul objet de style JSON, vous obtenez C#'S String.Format
comportement presque exactement.
"a{0}bcd{1}ef".formatUnicorn("foo", "bar"); // yields "aFOObcdBARef"
c'est parce que Array
's slice
va forcer tout ce qui est dans arguments
dans un Array
, qu'il était à l'origine ou non, et le key
sera l'indice (0, 1, 2...) de chaque élément de tableau contraint dans une chaîne (par exemple," 0", donc "\{0\}"
pour votre premier motif regexp).
Neat.
formatage du numéro en JavaScript
je suis arrivé à cette page de question en espérant trouver comment numéros de format en JavaScript, sans introduire encore une autre bibliothèque. Voici ce que j'ai trouvé:
Arrondissement des nombres à virgule flottante
l'équivalent de sprintf("%.2f", num)
en JavaScript semble être num.toFixed(2)
, qui formats num
à 2 décimales, avec arrondi (mais voir @ars265 commentaire à propos de Math.round
ci-dessous).
(12.345).toFixed(2); // returns "12.35" (rounding!)
(12.3).toFixed(2); // returns "12.30" (zero padding)
forme Exponentielle
l'équivalent de sprintf("%.2e", num)
est num.toExponential(2)
.
(33333).toExponential(2); // "3.33e+4"
bases hexadécimales et autres
pour imprimer les numéros de la base B, essayez num.toString(B)
. JavaScript prend en charge la conversion automatique vers et depuis les bases 2 à 36 (en outre, certains navigateurs ont prise en charge limitée pour le codage de base64 ).
(3735928559).toString(16); // to base 16: "deadbeef"
parseInt("deadbeef", 16); // from base 16: 3735928559
Pages De Référence
tutoriel rapide sur le formatage du numéro JS
Mozilla page de référence pour toFixed() (avec des liens vers toPrecision(), toExponential(), toLocaleString(), ...)
De l'ES6 sur, vous pourriez utiliser chaînes du modèle :
let soMany = 10;
console.log(`This is ${soMany} times easier!`);
// "This is 10 times easier!
soyez conscient que les chaînes de template sont entourées de bascules ` au lieu de (simple) guillemets.
pour plus d'informations:
https://developers.google.com/web/updates/2015/01/ES6-Template-Strings
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/template_strings
Note: Consultez le site mozilla pour trouver une liste des navigateurs pris en charge.
jsxt, Zippo
cette option convient mieux.
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;
};
avec cette option je peux remplacer des chaînes comme celles-ci:
'The {0} is dead. Don\'t code {0}. Code {1} that is open source!'.format('ASP', 'PHP');
avec votre code le second {0} ne serait pas remplacé. ;)
j'utilise cette fonction simple:
String.prototype.format = function() {
var formatted = this;
for( var arg in arguments ) {
formatted = formatted.replace("{" + arg + "}", arguments[arg]);
}
return formatted;
};
c'est très similaire à string.format:
"{0} is dead, but {1} is alive!".format("ASP", "ASP.NET")
voici un minimal implémentation de sprintf en JavaScript: il ne fait que "%s "et" %d", mais j'ai laissé de la place pour qu'il soit étendu. Il est inutile à L'OP, mais d'autres personnes qui trébuchent à travers ce fil venant de Google pourraient en bénéficier.
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;
});
}
exemple:
alert(sprintf('Latitude: %s, Longitude: %s, Count: %d', 41.847, -87.661, 'two'));
// Expected output: Latitude: 41.847, Longitude: -87.661, Count: 0
contrairement à des solutions similaires dans les réponses précédentes, celle-ci fait toutes les substitutions en une seule go , de sorte qu'il ne remplacera pas des parties de valeurs précédemment remplacées.
Pour Noeud.js les utilisateurs il y a util.format
qui a printf fonctionnalité:
util.format("%s world", "Hello")
je suis surpris que personne n'ait utilisé reduce
, il s'agit d'une fonction JavaScript concise et puissante native.
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'));
< ES6
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"
Comment cela fonctionne:
réduire applique une fonction à l'encontre d'un accumulateur et chaque élément de la matrice (de gauche à droite) réduire à une seule valeur.
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")
);
les programmeurs JavaScript peuvent utiliser la chaîne de caractères.prototype.sprintf à https://github.com/ildar-shaimordanov/jsxt/blob/master/js/String.js . En voici un exemple:
var d = new Date();
var dateStr = '%02d:%02d:%02d'.sprintf(
d.getHours(),
d.getMinutes(),
d.getSeconds());
+1 Zippo à l'exception que le corps de fonction doit être comme ci-dessous ou autrement il ajoute la chaîne courante sur chaque itération:
String.prototype.format = function() {
var formatted = this;
for (var arg in arguments) {
formatted = formatted.replace("{" + arg + "}", arguments[arg]);
}
return formatted;
};
ajoutant à la réponse de zippoxer
, j'utilise cette fonction:
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.
j'ai aussi une version non prototype que j'utilise plus souvent pour sa syntaxe Java:
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 mise à jour
tous les nouveaux trucs cool EN ES 2015 rend cela beaucoup plus facile:
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."
j'ai pensé que puisque ceci, comme les plus anciens, ne parsemble pas réellement les lettres, il pourrait aussi bien utiliser un jeton unique %%
. Cela a l'avantage d'être évident et de ne pas rendre difficile l'utilisation d'un seul %
. Cependant, si vous avez besoin de %%
pour une raison quelconque, vous devez le remplacer par lui-même:
format("I love percentage signs! %%", "%%");
// "I love percentage signs! %%"
très élégant:
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}")
le Crédit va à (lien brisé) https://gist.github.com/0i0/1519811
j'ajouterai mes propres découvertes que j'ai trouvées depuis que j'ai demandé:
- number_format (pour séparateur de milliers/monnaie de mise en forme)
- sprintf (même auteur que ci-dessus)
malheureusement, il semble que sprintf ne gère pas le formatage des milliers de séparateurs comme le format string de .NET.
j'utilise une petite bibliothèque appelée chaîne.format pour JavaScript qui supporte la plupart des capacités de la chaîne de format (y compris le format des nombres et des dates), et utilise la syntaxe .NET. Le script lui-même est plus petit que 4 kB, donc il ne crée pas beaucoup de overhead.
si vous cherchez à manipuler le séparateur de milliers, vous devez vraiment utiliser toLocaleString() de la classe JavaScript nombre car il formatera la chaîne de caractères pour la région de l'utilisateur.
la classe JavaScript Date peut formater des dates et des heures localisées.
je veux partager ma solution pour le "problème". Je n'ai pas réinventé la roue, mais j'essaie de trouver une solution basée sur ce que JavaScript fait déjà. L'avantage est que vous obtenez toutes les conversions implicites pour gratuit. Définir la propriété prototype $ of String donne une syntaxe très agréable et compacte (voir les exemples ci-dessous). Ce n'est peut-être pas le moyen le plus efficace, mais dans la plupart des cas traitant de la sortie, il ne doit pas être super optimisé.
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));
}
Voici quelques exemples:
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'
le PHPJS project a écrit des implémentations JavaScript pour de nombreuses fonctions de PHP. Puisque la fonction sprintf()
de PHP est fondamentalement la même que celle de C printf()
, leur implémentation JavaScript De it devrait satisfaire vos besoins.
j'utilise celui-ci:
String.prototype.format = function() {
var newStr = this, i = 0;
while (/%s/.test(newStr))
newStr = newStr.replace("%s", arguments[i++])
return newStr;
}
alors je l'appelle:
"<h1>%s</h1><p>%s</p>".format("Header", "Just a test!");
une version très légèrement différente, celle que je préfère (celle-ci utilise des arguments {xxx} tokens plutôt que des arguments {0} numérotés, c'est beaucoup plus auto-documentant et convient beaucoup mieux à la localisation):
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;
};
une variante serait:
var formatted = l(this);
qui appelle d'abord une fonction de localisation l ().
J'ai une solution très proche de celle de Peter, mais elle traite du cas du nombre et de l'objet.
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);
});
};
}
peut-être qu'il pourrait être encore mieux de traiter les cas tous les deeps, mais pour mes besoins, c'est très bien.
"This is an example from {name}".format({name:"Blaine"});
"This is an example from {0}".format("Blaine");
PS: cette fonction est très cool si vous utilisez des traductions dans des cadres de gabarits comme AngularJS :
<h1> {{('hello-message'|translate).format(user)}} <h1>
<h1> {{('hello-by-name'|translate).format( user ? user.name : 'You' )}} <h1>
Où la fr.json est quelque chose comme
{
"hello-message": "Hello {name}, welcome.",
"hello-by-name": "Hello {0}, welcome."
}
pour ceux qui aiment noeud.JS et son util.format
fonctionnalité, je viens de l'extraire dans sa forme JavaScript vanille (avec seulement des fonctions qui util.utilisation du format):
exports = {};
function isString(arg) {
return typeof arg === 'string';
}
function isNull(arg) {
return arg === null;
}
function isObject(arg) {
return typeof arg === 'object' && arg !== null;
}
function isBoolean(arg) {
return typeof arg === 'boolean';
}
function isUndefined(arg) {
return arg === void 0;
}
function stylizeNoColor(str, styleType) {
return str;
}
function stylizeWithColor(str, styleType) {
var style = inspect.styles[styleType];
if (style) {
return '\u001b[' + inspect.colors[style][0] + 'm' + str +
'\u001b[' + inspect.colors[style][3] + 'm';
} else {
return str;
}
}
function isFunction(arg) {
return typeof arg === 'function';
}
function isNumber(arg) {
return typeof arg === 'number';
}
function isSymbol(arg) {
return typeof arg === 'symbol';
}
function formatPrimitive(ctx, value) {
if (isUndefined(value))
return ctx.stylize('undefined', 'undefined');
if (isString(value)) {
var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
.replace(/'/g, "\'")
.replace(/\"/g, '"') + '\'';
return ctx.stylize(simple, 'string');
}
if (isNumber(value)) {
// Format -0 as '-0'. Strict equality won't distinguish 0 from -0,
// so instead we use the fact that 1 / -0 < 0 whereas 1 / 0 > 0 .
if (value === 0 && 1 / value < 0)
return ctx.stylize('-0', 'number');
return ctx.stylize('' + value, 'number');
}
if (isBoolean(value))
return ctx.stylize('' + value, 'boolean');
// For some reason typeof null is "object", so special case here.
if (isNull(value))
return ctx.stylize('null', 'null');
// es6 symbol primitive
if (isSymbol(value))
return ctx.stylize(value.toString(), 'symbol');
}
function arrayToHash(array) {
var hash = {};
array.forEach(function (val, idx) {
hash[val] = true;
});
return hash;
}
function objectToString(o) {
return Object.prototype.toString.call(o);
}
function isDate(d) {
return isObject(d) && objectToString(d) === '[object Date]';
}
function isError(e) {
return isObject(e) &&
(objectToString(e) === '[object Error]' || e instanceof Error);
}
function isRegExp(re) {
return isObject(re) && objectToString(re) === '[object RegExp]';
}
function formatError(value) {
return '[' + Error.prototype.toString.call(value) + ']';
}
function formatPrimitiveNoColor(ctx, value) {
var stylize = ctx.stylize;
ctx.stylize = stylizeNoColor;
var str = formatPrimitive(ctx, value);
ctx.stylize = stylize;
return str;
}
function isArray(ar) {
return Array.isArray(ar);
}
function hasOwnProperty(obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
var name, str, desc;
desc = Object.getOwnPropertyDescriptor(value, key) || {value: value[key]};
if (desc.get) {
if (desc.set) {
str = ctx.stylize('[Getter/Setter]', 'special');
} else {
str = ctx.stylize('[Getter]', 'special');
}
} else {
if (desc.set) {
str = ctx.stylize('[Setter]', 'special');
}
}
if (!hasOwnProperty(visibleKeys, key)) {
name = '[' + key + ']';
}
if (!str) {
if (ctx.seen.indexOf(desc.value) < 0) {
if (isNull(recurseTimes)) {
str = formatValue(ctx, desc.value, null);
} else {
str = formatValue(ctx, desc.value, recurseTimes - 1);
}
if (str.indexOf('\n') > -1) {
if (array) {
str = str.split('\n').map(function (line) {
return ' ' + line;
}).join('\n').substr(2);
} else {
str = '\n' + str.split('\n').map(function (line) {
return ' ' + line;
}).join('\n');
}
}
} else {
str = ctx.stylize('[Circular]', 'special');
}
}
if (isUndefined(name)) {
if (array && key.match(/^\d+$/)) {
return str;
}
name = JSON.stringify('' + key);
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
name = name.substr(1, name.length - 2);
name = ctx.stylize(name, 'name');
} else {
name = name.replace(/'/g, "\'")
.replace(/\"/g, '"')
.replace(/(^"|"$)/g, "'")
.replace(/\\/g, '\');
name = ctx.stylize(name, 'string');
}
}
return name + ': ' + str;
}
function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
var output = [];
for (var i = 0, l = value.length; i < l; ++i) {
if (hasOwnProperty(value, String(i))) {
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
String(i), true));
} else {
output.push('');
}
}
keys.forEach(function (key) {
if (!key.match(/^\d+$/)) {
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
key, true));
}
});
return output;
}
function reduceToSingleString(output, base, braces) {
var length = output.reduce(function (prev, cur) {
return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
}, 0);
if (length > 60) {
return braces[0] +
(base === '' ? '' : base + '\n ') +
' ' +
output.join(',\n ') +
' ' +
braces[1];
}
return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
}
function formatValue(ctx, value, recurseTimes) {
// Provide a hook for user-specified inspect functions.
// Check that value is an object with an inspect function on it
if (ctx.customInspect &&
value &&
isFunction(value.inspect) &&
// Filter out the util module, it's inspect function is special
value.inspect !== exports.inspect &&
// Also filter out any prototype objects using the circular check.
!(value.constructor && value.constructor.prototype === value)) {
var ret = value.inspect(recurseTimes, ctx);
if (!isString(ret)) {
ret = formatValue(ctx, ret, recurseTimes);
}
return ret;
}
// Primitive types cannot have properties
var primitive = formatPrimitive(ctx, value);
if (primitive) {
return primitive;
}
// Look up the keys of the object.
var keys = Object.keys(value);
var visibleKeys = arrayToHash(keys);
if (ctx.showHidden) {
keys = Object.getOwnPropertyNames(value);
}
// This could be a boxed primitive (new String(), etc.), check valueOf()
// NOTE: Avoid calling `valueOf` on `Date` instance because it will return
// a number which, when object has some additional user-stored `keys`,
// will be printed out.
var formatted;
var raw = value;
try {
// the .valueOf() call can fail for a multitude of reasons
if (!isDate(value))
raw = value.valueOf();
} catch (e) {
// ignore...
}
if (isString(raw)) {
// for boxed Strings, we have to remove the 0-n indexed entries,
// since they just noisey up the output and are redundant
keys = keys.filter(function (key) {
return !(key >= 0 && key < raw.length);
});
}
// Some type of object without properties can be shortcutted.
if (keys.length === 0) {
if (isFunction(value)) {
var name = value.name ? ': ' + value.name : '';
return ctx.stylize('[Function' + name + ']', 'special');
}
if (isRegExp(value)) {
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
}
if (isDate(value)) {
return ctx.stylize(Date.prototype.toString.call(value), 'date');
}
if (isError(value)) {
return formatError(value);
}
// now check the `raw` value to handle boxed primitives
if (isString(raw)) {
formatted = formatPrimitiveNoColor(ctx, raw);
return ctx.stylize('[String: ' + formatted + ']', 'string');
}
if (isNumber(raw)) {
formatted = formatPrimitiveNoColor(ctx, raw);
return ctx.stylize('[Number: ' + formatted + ']', 'number');
}
if (isBoolean(raw)) {
formatted = formatPrimitiveNoColor(ctx, raw);
return ctx.stylize('[Boolean: ' + formatted + ']', 'boolean');
}
}
var base = '', array = false, braces = ['{', '}'];
// Make Array say that they are Array
if (isArray(value)) {
array = true;
braces = ['[', ']'];
}
// Make functions say that they are functions
if (isFunction(value)) {
var n = value.name ? ': ' + value.name : '';
base = ' [Function' + n + ']';
}
// Make RegExps say that they are RegExps
if (isRegExp(value)) {
base = ' ' + RegExp.prototype.toString.call(value);
}
// Make dates with properties first say the date
if (isDate(value)) {
base = ' ' + Date.prototype.toUTCString.call(value);
}
// Make error with message first say the error
if (isError(value)) {
base = ' ' + formatError(value);
}
// Make boxed primitive Strings look like such
if (isString(raw)) {
formatted = formatPrimitiveNoColor(ctx, raw);
base = ' ' + '[String: ' + formatted + ']';
}
// Make boxed primitive Numbers look like such
if (isNumber(raw)) {
formatted = formatPrimitiveNoColor(ctx, raw);
base = ' ' + '[Number: ' + formatted + ']';
}
// Make boxed primitive Booleans look like such
if (isBoolean(raw)) {
formatted = formatPrimitiveNoColor(ctx, raw);
base = ' ' + '[Boolean: ' + formatted + ']';
}
if (keys.length === 0 && (!array || value.length === 0)) {
return braces[0] + base + braces[1];
}
if (recurseTimes < 0) {
if (isRegExp(value)) {
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
} else {
return ctx.stylize('[Object]', 'special');
}
}
ctx.seen.push(value);
var output;
if (array) {
output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
} else {
output = keys.map(function (key) {
return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
});
}
ctx.seen.pop();
return reduceToSingleString(output, base, braces);
}
function inspect(obj, opts) {
// default options
var ctx = {
seen: [],
stylize: stylizeNoColor
};
// legacy...
if (arguments.length >= 3) ctx.depth = arguments[2];
if (arguments.length >= 4) ctx.colors = arguments[3];
if (isBoolean(opts)) {
// legacy...
ctx.showHidden = opts;
} else if (opts) {
// got an "options" object
exports._extend(ctx, opts);
}
// set default options
if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
if (isUndefined(ctx.depth)) ctx.depth = 2;
if (isUndefined(ctx.colors)) ctx.colors = false;
if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
if (ctx.colors) ctx.stylize = stylizeWithColor;
return formatValue(ctx, obj, ctx.depth);
}
exports.inspect = inspect;
// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
inspect.colors = {
'bold': [1, 22],
'italic': [3, 23],
'underline': [4, 24],
'inverse': [7, 27],
'white': [37, 39],
'grey': [90, 39],
'black': [30, 39],
'blue': [34, 39],
'cyan': [36, 39],
'green': [32, 39],
'magenta': [35, 39],
'red': [31, 39],
'yellow': [33, 39]
};
// Don't use 'blue' not visible on cmd.exe
inspect.styles = {
'special': 'cyan',
'number': 'yellow',
'boolean': 'yellow',
'undefined': 'grey',
'null': 'bold',
'string': 'green',
'symbol': 'green',
'date': 'magenta',
// "name": intentionally not styling
'regexp': 'red'
};
var formatRegExp = /%[sdj%]/g;
exports.format = function (f) {
if (!isString(f)) {
var objects = [];
for (var j = 0; j < arguments.length; j++) {
objects.push(inspect(arguments[j]));
}
return objects.join(' ');
}
var i = 1;
var args = arguments;
var len = args.length;
var str = String(f).replace(formatRegExp, function (x) {
if (x === '%%') return '%';
if (i >= len) return x;
switch (x) {
case '%s':
return String(args[i++]);
case '%d':
return Number(args[i++]);
case '%j':
try {
return JSON.stringify(args[i++]);
} catch (_) {
return '[Circular]';
}
default:
return x;
}
});
for (var x = args[i]; i < len; x = args[++i]) {
if (isNull(x) || !isObject(x)) {
str += ' ' + x;
} else {
str += ' ' + inspect(x);
}
}
return str;
};
récolté à partir de: https://github.com/joyent/node/blob/master/lib/util.js
il y a "sprintf" pour JavaScript que vous pouvez trouver à http://www.webtoolkit.info/javascript-sprintf.html .
j'ai un formater légèrement plus long pour JavaScript ici ...
vous pouvez faire le formatage de plusieurs façons:
-
String.format(input, args0, arg1, ...)
-
String.format(input, obj)
-
"literal".format(arg0, arg1, ...)
-
"literal".format(obj)
aussi, si vous avez dit une ObjectBase.prototype.format (comme avec DateJS ) il utilisera que.
exemples...
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})"
j'ai aussi aliasé avec .asFormat et avoir un peu de détection en place au cas où il y a déjà une chaîne.format (comme avec la boîte à outils de MS Ajax (je déteste cette bibliothèque).
juste au cas où quelqu'un a besoin d'une fonction pour empêcher la portée globale polluante, voici la fonction qui fait la même chose:
function _format (str, arr) {
return str.replace(/{(\d+)}/g, function (match, number) {
return typeof arr[number] != 'undefined' ? arr[number] : match;
});
};
pour le formatage de base:
var template = jQuery.validator.format("{0} is not a valid value");
var result = template("abc");
Je n'ai pas vu la variante String.format
:
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;
});
};
Je n'ai pas vu pyformat dans la liste donc j'ai pensé que j'allais le jeter dans:
console.log(pyformat( 'The {} {} jumped over the {}'
, ['brown' ,'fox' ,'foobar']
))
console.log(pyformat('The {0} {1} jumped over the {1}'
, ['brown' ,'fox' ,'foobar']
))
console.log(pyformat('The {color} {animal} jumped over the {thing}'
, [] ,{color: 'brown' ,animal: 'fox' ,thing: 'foobaz'}
))
/**
* Format string by replacing placeholders with value from element with
* corresponsing index in `replacementArray`.
* Replaces are made simultaneously, so that replacement values like
* '{1}' will not mess up the function.
*
* Example 1:
* ('{2} {1} {0}', ['three', 'two' ,'one']) -> 'one two three'
*
* Example 2:
* ('{0}{1}', ['{1}', '{0}']) -> '{1}{0}'
*/
function stringFormat(formatString, replacementArray) {
return formatString.replace(
/\{(\d+)\}/g, // Matches placeholders, e.g. '{1}'
function formatStringReplacer(match, placeholderIndex) {
// Convert String to Number
placeholderIndex = Number(placeholderIndex);
// Make sure that index is within replacement array bounds
if (placeholderIndex < 0 ||
placeholderIndex > replacementArray.length - 1
) {
return placeholderIndex;
}
// Replace placeholder with value from replacement array
return replacementArray[placeholderIndex];
}
);
}