Je cherche un bon équivalent JavaScript de C/PHP printf()
ou des programmeurs C #/Java, String.Format()
(IFormatProvider
pour .NET).
Mon exigence de base est un format de séparateur de milliers pour les chiffres pour le moment, mais quelque chose qui gère beaucoup de combinaisons (y compris les dates) serait bien.
Je me rends compte que la bibliothèque Ajax de Microsoft fournit une version de String.Format()
, mais nous ne voulons pas de la surcharge totale de ce framework.
À partir de ES6, vous pouvez utiliser des chaînes de modèle:
let soMany = 10;
console.log(`This is ${soMany} times easier!`);
// "This is 10 times easier!
Voir Kim's réponse ci-dessous pour plus de détails.
Essayez sprintf () pour JavaScript .
Si vous voulez vraiment faire vous-même une méthode de formatage simple, ne faites pas les remplacements successivement, mais faites-les simultanément.
Parce que la plupart des autres propositions mentionnées échouent lorsqu'une chaîne de remplacement d'un remplacement précédent contient également une séquence de format similaire à celle-ci:
"{0}{1}".format("{1}", "{0}")
Normalement, vous vous attendez à ce que la sortie soit {1}{0}
mais la sortie réelle est {1}{1}
. Par conséquent, effectuez un remplacement simultané, comme dans suggestion de fearphage .
Construire 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")
les sorties
ASP est mort, mais ASP.NET est vivant! ASP {2}
Si vous préférez ne pas modifier le prototype de String
:
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 le 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 amusant parce que Stack Overflow possède sa propre fonction de formatage pour le prototype String
appelé formatUnicorn
. Essayez le! Allez dans la console et tapez quelque chose comme:
_"Hello, {name}, are you feeling {adjective}?".formatUnicorn({name:"Gabriel", adjective: "OK"});
_
Vous obtenez cette sortie:
_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 l'ai 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 astucieux Array.prototype.slice.call(arguments)
- cela signifie que si vous ajoutez des arguments sous forme de chaînes ou de chiffres, et non un seul objet de style JSON, vous obtenez le comportement de C # String.Format
presque exactement .
_"a{0}bcd{1}ef".formatUnicorn("foo", "bar"); // yields "aFOObcdBARef"
_
C'est parce que Array
de slice
va forcer tout ce qui se trouve dans arguments
dans un Array
, que ce soit à l'origine ou non, et le key
sera l'index (0, 1, 2 ...) de chaque élément de tableau contraint dans une chaîne (par exemple, "0", donc _"\\{0\\}"
_ pour votre premier motif d'expression rationnelle).
Soigné.
Je suis arrivé à cette page de question dans l'espoir de trouver comment formater des nombres en JavaScript, sans introduire une autre bibliothèque. Voici ce que j'ai trouvé:
L'équivalent de sprintf("%.2f", num)
dans JavaScript semble être num.toFixed(2)
, qui formate num
avec 2 décimales, avec arrondi (voir le commentaire de @ ars265 sur Math.round
ci-dessous).
(12.345).toFixed(2); // returns "12.35" (rounding!)
(12.3).toFixed(2); // returns "12.30" (zero padding)
L'équivalent de sprintf("%.2e", num)
est num.toExponential(2)
.
(33333).toExponential(2); // "3.33e+4"
Pour imprimer des nombres en base B, essayez num.toString(B)
. JavaScript prend en charge la conversion automatique vers et à partir des bases 2 à 36 (certains navigateurs ont en outre prise en charge limitée du codage base64 ).
(3735928559).toString(16); // to base 16: "deadbeef"
parseInt("deadbeef", 16); // from base 16: 3735928559
Petit tutoriel sur le formatage des nombres JS
page de référence de Mozilla pour toFixed () (avec des liens vers toPrecision (), toExponential (), toLocaleString (), ...)
A partir de ES6, vous pouvez utiliser des chaînes de modèle :
let soMany = 10;
console.log(`This is ${soMany} times easier!`);
// "This is 10 times easier!
Sachez que les chaînes de modèles sont entourées de guillemets `au lieu de guillemets (simples).
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
Remarque: Consultez le site mozilla pour trouver la 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 sera 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")
Pour Node.js utilisateurs, il y a util.format
qui a une fonctionnalité analogue à celle de printf:
_util.format("%s world", "Hello")
_
Voici une minimale implémentation de sprintf en JavaScript: elle ne fait que "% s" et "% d", mais j'ai laissé de la place pour son extension. Cela ne sert à rien pour le PO, mais d’autres personnes qui tombent sur ce fil venant de Google pourraient en tirer profit.
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 aux solutions similaires des réponses précédentes, celle-ci effectue toutes les substitutions en une fois, de sorte qu'elle ne remplacera pas des parties des valeurs précédemment remplacées.
Je suis surpris que personne ne l'utilise reduce
, il s'agit d'une fonction JavaScript native concise et puissante.
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"
Comment ça fonctionne:
reduction applique une fonction à un accumulateur et à chaque élément du tableau (de gauche à droite) pour le réduire à une valeur unique.
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 String.prototype.sprintf à l'adresse https://github.com/ildar-shaimordanov/jsxt/blob/master/js/String.js . Voici un exemple:
var d = new Date();
var dateStr = '%02d:%02d:%02d'.sprintf(
d.getHours(),
d.getMinutes(),
d.getSeconds());
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 également une version non-prototype que j'utilise plus souvent pour sa syntaxe semblable à 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
Toutes les nouvelles fonctionnalités d'ES 2015 facilitent grandement la tâche:
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."
Je me suis dit que puisque ceci, comme les plus anciens, n'analyse pas réellement les lettres, il pourrait tout aussi bien utiliser un seul jeton %%
. Cela présente 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 devrez le remplacer par lui-même:
format("I love percentage signs! %%", "%%");
// "I love percentage signs! %%"
+1 Zippo avec l'exception que le corps de la fonction doit être comme ci-dessous ou sinon il ajoute la chaîne en cours à chaque itération:
String.prototype.format = function() {
var formatted = this;
for (var arg in arguments) {
formatted = formatted.replace("{" + arg + "}", arguments[arg]);
}
return formatted;
};
J'ajouterai mes propres découvertes que j'ai découvertes depuis que j'ai demandé:
Malheureusement, il semble que sprintf ne gère pas le formatage des séparateurs de milliers, comme le format de chaîne de .NET.
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'utilise une petite bibliothèque appelée String.format pour JavaScript , qui prend en charge la plupart des fonctionnalités de formatage de chaîne (y compris le format des nombres et des dates) et utilise la syntaxe .NET. Le script lui-même est inférieur à 4 Ko, il ne génère donc pas beaucoup de temps système.
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 gratuitement. La définition de 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, le rendement ne doit pas être 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'
J'ai une solution très proche de celle de Peter, mais elle traite du nombre et de la cause 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 serait-il encore mieux de traiter les cas graves, 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 pratique si vous utilisez des traductions dans des frameworks de templates tels que AngularJS :
<h1> {{('hello-message'|translate).format(user)}} <h1>
<h1> {{('hello-by-name'|translate).format( user ? user.name : 'You' )}} <h1>
Où le en.json est quelque chose comme
{
"hello-message": "Hello {name}, welcome.",
"hello-by-name": "Hello {0}, welcome."
}
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!");
Le projet PHPJS a écrit des implémentations JavaScript pour de nombreuses fonctions de PHP. Puisque la fonction sprintf()
de PHP est fondamentalement identique à celle de printf()
, de C, leur implémentation JavaScript devrait répondre à vos besoins.
Une version très légèrement différente, celle que je préfère (celle-ci utilise {xxx} jetons au lieu de {0} arguments numérotés, elle est beaucoup plus documentée et convient 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 variation serait:
var formatted = l(this);
qui appelle une fonction de localisation l() en premier.
Pour ceux qui aiment Node.JS et sa fonctionnalité util.format
, je viens de l'extraire dans sa forme JavaScript Vanilla (avec uniquement les fonctions util.format les usages):
_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é depuis: https://github.com/joyent/node/blob/master/lib/util.js
Il existe "sprintf" pour JavaScript que vous pouvez trouver sur http://www.webtoolkit.info/javascript-sprintf.html .
Juste au cas où quelqu'un aurait besoin d'une fonction anti-pollution globale, 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");
J'ai un formateur légèrement plus long pour JavaScript ici ...
Vous pouvez effectuer le formatage de plusieurs manières:
String.format(input, args0, arg1, ...)
String.format(input, obj)
"literal".format(arg0, arg1, ...)
"literal".format(obj)
De même, si vous avez déclaré un ObjectBase.prototype.format (tel que DateJS ), il l'utilisera.
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 également créé un alias avec .asFormat et une certaine détection est en place au cas où il existe déjà un string.format (comme avec MS Ajax Toolkit (je déteste cette bibliothèque).
En utilisant Lodash , vous pouvez obtenir la fonctionnalité de modèle:
Utilisez le délimiteur de littéral de modèle ES en tant que délimiteur "interpoler". Désactivez la prise en charge en remplaçant le délimiteur "interpoler".
var compiled = _.template('hello ${ user }!');
compiled({ 'user': 'pebbles' });
// => 'hello pebbles!
À utiliser avec les fonctions de réussite jQuery.ajax (). Ne passez qu'un seul argument et remplacez la chaîne par les propriétés de cet objet sous la forme {propertyName}:
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;
};
Exemple:
var userInfo = ("Email: {Email} - Phone: {Phone}").format({ Email: "[email protected]", Phone: "123-123-1234" });
Je n'ai pas vu pyformat dans la liste et j'ai donc pensé l'inclure:
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];
}
);
}
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;
});
};
Avec sprintf.js en place, on peut faire un joli petit format
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}
Il y a aussi Globalize.format
dans le projet jQuery Globalize , le service de globalisation officiel de jQuery UI. C’est bien quand vous avez besoin d’un formatage tenant compte de la culture.
J'avais besoin d'une fonction permettant de formater un prix (exprimé en centimes) de la manière préférée par l'utilisateur. Le problème, c'est que le format est spécifié par l'utilisateur - et je ne m'attends pas à ce que mes utilisateurs comprennent la syntaxe similaire à printf , ou regexps, etc. Ma solution est quelque peu similaire à celle utilisée dans Basic, de sorte que l'utilisateur ne marque qu'avec # d'emplacements pour les chiffres, par exemple:
simple_format(1234567,"$ ###,###,###.##")
"$ 12,345.67"
simple_format(1234567,"### ### ###,## pln")
"12 345,67 pln"
Je pense que cela est assez facile à comprendre par l'utilisateur et assez facile à implémenter:
function simple_format(integer,format){
var text = "";
for(var i=format.length;i--;){
if(format[i]=='#'){
text = (integer%10) + text;
integer=Math.floor(integer/10);
if(integer==0){
return format.substr(0,i).replace(/#(.*#)?/,"")+text;
}
}else{
text = format[i] + text;
}
}
return text;
}
arg
fonction:
/**
* Qt stil arg()
* var scr = "<div id='%1' class='%2'></div>".arg("mydiv").arg("mydivClass");
*/
String.prototype.arg = function() {
var signIndex = this.indexOf("%");
var result = this;
if (signIndex > -1 && arguments.length > 0) {
var argNumber = this.charAt(signIndex + 1);
var _arg = "%"+argNumber;
var argCount = this.split(_arg);
for (var itemIndex = 0; itemIndex < argCount.length; itemIndex++) {
result = result.replace(_arg, arguments[0]);
}
}
return result;
}
Nous pouvons utiliser une bibliothèque d'opérations chaîne légère et légère String.Format pour TypeScript.
String.Format ():
var id = image.GetId()
String.Format("image_{0}.jpg", id)
output: "image_2db5da20-1c5d-4f1a-8fd4-b41e34c8c5b5.jpg";
Format de chaîne pour les spécificateurs:
var value = String.Format("{0:L}", "Apple"); //output "Apple"
value = String.Format("{0:U}", "Apple"); // output "Apple"
value = String.Format("{0:d}", "2017-01-23 00:00"); //output "23.01.2017"
value = String.Format("{0:s}", "21.03.2017 22:15:01") //output "2017-03-21T22:15:01"
value = String.Format("{0:n}", 1000000);
//output "1.000.000"
value = String.Format("{0:00}", 1);
//output "01"
Format de chaîne pour les objets, y compris les spécificateurs:
var fruit = new Fruit();
fruit.type = "Apple";
fruit.color = "RED";
fruit.shippingDate = new Date(2018, 1, 1);
fruit.amount = 10000;
String.Format("the {type:U} is {color:L} shipped on {shippingDate:s} with an amount of {amount:n}", fruit);
// output: the Apple is red shipped on 2018-01-01 with an amount of 10.000
bobjs peut le faire:
var sFormat = "My name is {0} and I am {1} years old.";
var result = bob.string.formatString(sFormat, "Bob", 29);
console.log(result);
//output:
//==========
// My name is Bob and I am 29 years old.
Ce n'est pas une copie exacte de sprintf
; cependant, il est similaire et plus puissant: https://github.com/anywhichway/stringformatter
Les expressions de format utilisant cette bibliothèque se présentent sous la forme d'objets Javascript incorporés, par exemple.
format("I have {number: {currency: "$", precision:2}}.",50.2);
retournera "I have $50.20."
.
Celui-ci fonctionne avec {0}, {1} et {}.
String.prototype.format = function format()
{
var msg = this;
for(var i in arguments)
msg = msg.replace(/\{\}/,arguments[i]).replace(new RegExp('\\{'+i+'\\}','g'),arguments[i]);
return msg;
}
J'ai commencé à porter Java
String.format
(en fait, nouveau Formatter (). Format ()) en javascript. La version initiale est disponible à l'adresse suivante:
https://github.com/RobAu/javascript.string.format
Vous pouvez simplement ajouter le javscript et appeler StringFormat.format("%.2f", [2.4]);
etc.
S'il vous plaît noter qu'il n'est pas encore terminé, mais les commentaires sont les bienvenus :)
String.prototype.repeat = function(n) {
return new Array(++n).join(this);
};
String.prototype.pad = function(requiredLength, paddingStr, paddingType) {
var n = requiredLength - this.length;
if (n) {
paddingType = paddingType ? paddingType.toLowerCase() : '';
paddingStr = paddingStr || ' ';
paddingStr = paddingStr.repeat( Math.ceil(n / paddingStr.length) ).substr(0, n);
if (paddingType == 'both') {
n /= 2;
return paddingStr.substr( 0, Math.ceil(n) ) + this + paddingStr.substr( 0, Math.floor(n) );
}
if (paddingType == 'left') {
return paddingStr + this;
}
return this + paddingStr;
}
return this;
};
// синтаксис аналогичен printf
// 'Привет, %s!'.format('мир') -> "Привет, мир!"
// '%.1s.%.1s. %s'.format('Иван', 'Иванович', 'Иванов') -> "И.И. Иванов"
String.prototype.format = function() {
var i = 0,
params = arguments;
return this.replace(/%(?:%|(?:(|[+-]+)(|0|'.+?)([1-9]\d*)?(?:\.([1-9]\d*))?)?(s|d|f))/g, function(match, sign, padding, width, precision, type) {
if (match == '%%') {
return '%';
}
var v = params[i++];
if (type == 'd') {
v = Math.round(v);
}
else if (type == 'f') {
v = v.toFixed(precision ? precision : 6);
}
if (/\+/.test(sign) && v > 0) {
v = '+' + v;
}
v += '';
if (type != 'f' && precision) {
v = v.substr(0, precision);
}
if (width) {
v = v.pad(width, padding == '' ? ' ' : padding[0] == "'" ? padding.substr(1) : padding, /-/.test(sign) ? 'right' : 'left');
}
return v;
});
};
// this.name = 'Вася';
// console.log( 'Привет, ${name}!'.template(this) );
// "Привет, Вася!"
String.prototype.template = function(context) {
return this.replace(/\$\{(.*?)\}/g, function(match, name) {
return context[name];
});
};
String.prototype.format = function(){
var final = String(this);
for(let i=0; i<arguments.length;i++){
final = final.replace(`%s${i+1}`, arguments[i])
}
return final || ''
}
console.log(("hello %s2 how %s3 you %s1").format('hi', 'hello', 'how'));
<h1 id="text">
</h1>
Vous pouvez utiliser cette fonction
String.prototype.format = function (args) {
var str = this;
return str.replace(String.prototype.format.regex, function(item) {
var intVal = parseInt(item.substring(1, item.length - 1));
var replace;
if (intVal >= 0) {
replace = args[intVal];
} else if (intVal === -1) {
replace = "{";
} else if (intVal === -2) {
replace = "}";
} else {
replace = "";
}
return replace;
});
};
String.prototype.format.regex = new RegExp("{-?[0-9]+}", "g");
// Sample usage.
var str = "She {1} {0}{2} by the {0}{3}. {-1}^_^{-2}";
str = str.format(["sea", "sells", "shells", "shore"]);
alert(str);