相当于printf/String. Format的JavaScript

我正在寻找一个好的JavaScript相当于C/PHPprintf()或C#/Java程序员,String.Format()IFormatProvider for. NET)。

我的基本要求是现在数字的一千个分隔符格式,但是处理大量组合(包括日期)的东西会很好。

我知道Microsoft的Ajax库提供了String.Format()的版本,但我们不希望该框架的全部开销。

2253326 次浏览

当前的javascript

从ES6开始,您可以使用模板字符串:

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

有关详细信息,请参阅下面的Kim回答


老答案

试试JavaScript的Sprintf()


如果你真的想自己做一个简单的格式方法,不要连续做替换,而是同时做。

因为当先前替换的替换字符串也包含这样的格式序列时,提到的大多数其他建议都会失败:

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

通常你会期望输出为{1}{0},但实际输出为{1}{1}。所以像恐惧噬菌体的建议一样进行同时替换。

有一个JavaScript的“print intf”,你可以在http://www.webtoolkit.info/javascript-sprintf.html找到。

我将添加我自己的发现,因为我问:

可悲的是,似乎spintf不能像. NET的字符串格式那样处理数千个分隔符格式。

如果您希望处理千分隔符,您应该真正使用JavaScript数量类中的toLocaleString(),因为它将为用户的区域格式化字符串。

JavaScript日期类可以格式化本地化的日期和时间。

我使用一个名为String.formatJavaScript的小型库,它支持大多数格式字符串功能(包括数字和日期的格式),并使用. NET语法。脚本本身小于4 kB,因此不会产生太多开销。

我使用这个简单的函数:

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

这与string.format非常相似:

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

+1 Zippo,除了函数体需要如下所示,否则它会在每次迭代时附加当前字符串:

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

JavaScript程序员可以在https://github.com/ildar-shaimordanov/jsxt/blob/master/js/String.js使用String.prototype.sprintf。以下是示例:

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

jsxt,Zippo

这个选项更合适。

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

使用此选项,我可以替换这样的字符串:

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

使用您的代码,第二个{0}不会被替换。;)

基于先前建议的解决方案:

// 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")

产出

ASP死了,但ASP.NET还活着!


如果你不想修改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;});};}

让你更加熟悉:

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

得到同样的结果:

ASP死了,但ASP.NET还活着!

这是JavaScript中print intf的最小实现:它只执行“%s”和“%d”,但我已经为它留出了扩展的空间。这对OP毫无用处,但其他偶然发现这个来自Google的线程的人可能会从中受益。

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, %dvar val = null;if (m[2]) {val = m[2];} else {val = args[i];// A switch statement so that the formatter can be extended. Default is %sswitch (m) {case '%d':val = parseFloat(val);if (isNaN(val)) {val = 0;}break;}i++;}return val;});}

示例:

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

与之前回复中的类似解决方案相比,此解决方案执行所有替换一气呵成,因此不会替换先前替换的值的部分。

PHPJS项目已经为PHP的许多函数编写了JavaScript实现。由于PHP的sprintf()函数与C的printf()基本相同,它的JavaScript实现应该可以满足您的需求。

arg函数:

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

jQuery全球化项目中还有Globalize.format,这是jQuery UI的官方全球化服务。当你需要文化感知格式时,它很好。

JavaScript中的数字格式

我来到这个问题页面,希望找到如何在JavaScript中格式号,而不引入另一个库。这是我发现的:

舍入浮点数

在JavaScript中,sprintf("%.2f", num)的等价物似乎是num.toFixed(2),它将num格式化为小数点后2位,并四舍五入(但请参阅@ars265关于Math.round的评论)。

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

指数形式

sprintf("%.2e", num)的等价物是num.toExponential(2)

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

十六进制和其他基地

要以B为基数打印数字,请尝试num.toString(B)。JavaScript支持从2到36的自动转换(此外,某些浏览器有对Base64编码的有限支持)。

(3735928559).toString(16); // to base 16: "deadbeef"parseInt("deadbeef", 16); // from base 16: 3735928559

参考页面

JS数字格式快速教程

mozilla引用页面toFixt()(链接到toPreilling(),toExPonential(),toLocaleString(),…)

非常优雅:

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

信用去(断开的链接)https://gist.github.com/0i0/1519811

我有一个稍微长一点的JavaScript这里格式化程序…

您可以通过多种方式进行格式化:

  • String.format(input, args0, arg1, ...)
  • String.format(input, obj)
  • "literal".format(arg0, arg1, ...)
  • "literal".format(obj)

此外,如果你说一个ObjectBase.prototype.format(例如DateJS),它将使用它。

例子…

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

我还使用了. asFormat别名,并在已经有string.format的情况下进行了一些检测(例如使用MS Ajax Toolkit(我讨厌那个库)。

这一个适用于{0}、{1}和{}。

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

我没有看到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;});};

一个略有不同的版本,我更喜欢的版本(这个使用{xxx}令牌而不是{0}编号参数,这更具自文档性,更适合本地化):

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

一种变体是:

  var formatted = l(this);

首先调用l()本地化函数。

我想分享我对“问题”的解决方案。我没有重新发明轮子,而是试图根据JavaScript已经做的事情找到一个解决方案。优点是,你可以免费获得所有隐式转换。设置String的原型属性$给出了一个非常好和紧凑的语法(参见下面的示例)。这可能不是最有效的方法,但在大多数情况下处理输出时,它不需要超级优化。

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

以下是几个例子:

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'

您可以使用此功能

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

与jQuery.ajax()成功函数一起使用。仅传递一个参数和字符串替换,并将该对象的属性作为{属性名称}:

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

示例:

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

有了sprintf.js-人们可以制作一个漂亮的小格式

String.prototype.format = function(){var _args = argumentsArray.prototype.unshift.apply(_args,[this])return sprintf.apply(undefined,_args)}// this gives you:"{%1$s}{%2$s}".format("1", "0")// {1}{0}

添加到zippoxer的答案,我使用这个函数:

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.

我还有一个非原型版本,我经常使用它的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

es2015更新

在ES 2015中所有很酷的新东西使这变得容易得多:

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

我想,因为这和旧的一样,实际上不会解析字母,所以它不妨只使用单个标记%%。这的好处是显而易见的,并且不会让使用单个%变得困难。然而,如果你出于某种原因需要%%,你需要用它自己替换它:

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

bobjs可以这样做:

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

这是CoffeeScript的https://stackoverflow.com/a/4673436/1258486实现。

https://gist.github.com/eces/5669361

if String.prototype.format is undefinedString.prototype.format = () ->_arguments = argumentsthis.replace /{(\d+)}/g, (match, number) ->if typeof _arguments[number] isnt 'undefined' then _arguments[number] else match

我需要一个函数,它可以以用户喜欢的方式格式化价格(以美分为单位),而棘手的部分是格式是由用户指定的——我不希望我的用户理解类似printf的语法或正则表达式等。我的解决方案有点类似于Basic中使用的解决方案,因此用户只需用#位标记数字,例如:

simple_format(1234567,"$ ###,###,###.##")"$ 12,345.67"simple_format(1234567,"### ### ###,## pln")"12 345,67 pln"

我相信这很容易被用户理解,也很容易实现:

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

这很有趣,因为Stack Overflow实际上为名为formatUnicornString原型提供了自己的格式化功能。试试吧!进入控制台并输入以下内容:

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

Firebug

你得到这个输出:

Hello, Gabriel, are you feeling OK?

你可以使用对象、数组和字符串作为参数!我得到了它的代码并重新工作以生成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;};

请注意巧妙的Array.prototype.slice.call(arguments)调用——这意味着如果您输入的参数是字符串或数字,而不是单个JSON风格的对象,您几乎可以准确地获得C#的#1行为。

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

这是因为Arrayslice将强制arguments中的任何内容进入Array,无论它最初是否是,并且key将是强制转换为字符串的每个数组元素的索引(0,1,2…)(例如,“0”,因此"\\{0\\}"为您的第一个regexp模式)。

整洁。

我用这个:

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

然后我叫它:

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

对于Node.js用户,有#0具有类似printf的功能:

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

我有一个非常接近彼得的解决方案,但它涉及数字和对象的情况。

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

也许处理所有深度病例会更好,但对于我的需要,这很好。

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

PS:如果您在AngularJS这样的模板框架中使用翻译,这个函数非常酷:

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

en.json就像

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

我在列表中没有看到pyforma,所以我想把它扔进去:

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

我开始将JavaString.format(实际上是新的For的(). form())移植到javascript。初始版本可在以下位置获得:

您可以简单地添加javcript并调用StringFormat.format("%.2f", [2.4]);等。

请注意,它还没有完成,但欢迎反馈:)

如果有人需要一个函数来防止污染全局范围,下面是执行相同操作的函数:

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

对于那些喜欢Node.JS#0功能的人,我刚刚将其提取到其vanilla JavaScript形式中(仅包含util.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 primitiveif (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 itif (ctx.customInspect &&value &&isFunction(value.inspect) &&// Filter out the util module, it's inspect function is specialvalue.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 propertiesvar 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 reasonsif (!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 redundantkeys = 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 primitivesif (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 Arrayif (isArray(value)) {array = true;braces = ['[', ']'];}
// Make functions say that they are functionsif (isFunction(value)) {var n = value.name ? ': ' + value.name : '';base = ' [Function' + n + ']';}
// Make RegExps say that they are RegExpsif (isRegExp(value)) {base = ' ' + RegExp.prototype.toString.call(value);}
// Make dates with properties first say the dateif (isDate(value)) {base = ' ' + Date.prototype.toUTCString.call(value);}
// Make error with message first say the errorif (isError(value)) {base = ' ' + formatError(value);}
// Make boxed primitive Strings look like suchif (isString(raw)) {formatted = formatPrimitiveNoColor(ctx, raw);base = ' ' + '[String: ' + formatted + ']';}
// Make boxed primitive Numbers look like suchif (isNumber(raw)) {formatted = formatPrimitiveNoColor(ctx, raw);base = ' ' + '[Number: ' + formatted + ']';}
// Make boxed primitive Booleans look like suchif (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 optionsvar 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" objectexports._extend(ctx, opts);}// set default optionsif (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#graphicsinspect.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.exeinspect.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;};

收割自:https://github.com/joyent/node/blob/master/lib/util.js

我很惊讶没有人使用#0,这是一个原生简洁而强大的JavaScript函数。

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"

它是如何工作的:

减少对累加器和数组中的每个元素(从左到右)应用一个函数以将其减少为单个值。

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

从ES6开始,您可以使用模板字符串

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

请注意,模板字符串是被背影包围'而不是(单引号)引号。

更多信息:

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

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

注意:检查mozilla站点以查找支持的浏览器列表。

对于基本格式:

var template = jQuery.validator.format("{0} is not a valid value");var result = template("abc");
/*** 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 NumberplaceholderIndex = Number(placeholderIndex);
// Make sure that index is within replacement array boundsif (placeholderIndex < 0 ||placeholderIndex > replacementArray.length - 1) {return placeholderIndex;}
// Replace placeholder with value from replacement arrayreturn replacementArray[placeholderIndex];});}

这不是sprintf的精确副本;然而,它是相似的,更强大:https://github.com/anywhichway/stringformatter

使用此库的格式表达式采用嵌入式Javascript对象的形式,例如。

format("I have {number: {currency: "$", precision:2}}.",50.2);

将返回"I have $50.20."

使用Lodash可以获得模板功能:

使用ES模板文字分隔符作为“插值”分隔符。通过替换“插值”分隔符禁用支持。

var compiled = _.template('hello ${ user }!');compiled({ 'user': 'pebbles' });// => 'hello pebbles!

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>

我们可以为TypeScript使用一个简单的轻量级字符串格式字符串操作库。

String. Format():是否必选

var id = image.GetId()String.Format("image_{0}.jpg", id)output: "image_2db5da20-1c5d-4f1a-8fd4-b41e34c8c5b5.jpg";

说明符的字符串格式:

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"

包含说明符的对象的字符串格式:

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
export function stringFormat (str: string, ...args: string[]) {return args.reduce((acc, curr, i) => acc.replace(new RegExp("\\{" + i + "\\}", 'g'), curr), str);}

在打字稿中创建一个名为format.ts的文件并导入任何您需要使用格式的文件。

// contents of format.ts
interface String {format(...args: any[]): string;}
if (!String.prototype.format) {String.prototype.format = function() {let a = this;let b: any;// tslint:disable-next-line: forinfor (b in arguments) {a = a.replace(/%[a-z]/, arguments[b]);}return a;};}

要格式化字符串,请使用此代码:

import './format';
console.log('Hello, %s!'.format('World'));

示例

String.prototype.format = function() {let a = this;let b;for (b in arguments) {a = a.replace(/%[a-z]/, arguments[b]);}return a;};
console.log('Hello, %s!'.format('World'));

另一个建议是使用字符串模板:

const getPathDadosCidades = (id: string) =>  `/clientes/${id}`
const getPathDadosCidades = (id: string, role: string) =>  `/clientes/${id}/roles/${role}`

不是世界上最推荐的功能,但它有效。

如果你需要spintf,只需复制和粘贴这个相同的函数并将return console.log(sb)更改为return sb

printf = function(s, /*args...*/) {a = arguments;al = a.length;    
if (al <= 1) return -2;if (al >= 2 && s.toLowerCase().search(/%[a-z]/) == -1) return -1;
sb = s;for (i = 1; i <= al - 1; i++) {sb = sb.replace(/%[a-z]/, a[i]);}
return console.log(sb);}
var someString = "Hello %s\nIt's %s:%s %s now.\nThe day is %s\n";printf(someString, "StackOverflowUser", "5", "48", "PM", "beautiful");

如果您只需要使用%s说明符格式化字符串

function _sprintf(message){const regexp = RegExp('%s','g');let match;let index = 1;while((match = regexp.exec(message)) !== null) {let replacement = arguments[index];if (replacement) {let messageToArray = message.split('');messageToArray.splice(match.index, regexp.lastIndex - match.index, replacement);message = messageToArray.join('');index++;} else {break;}}
return message;}
_sprintf("my name is %s, my age is %s", "bob", 50); // my name is bob, my age is 50

斯普林特函数函数模拟在JavaScript中作为Vue过滤器String.prototype.format()扩展:

/*** Returns a formatted string.** @param template* @param values* @return string*/String.format = function (template, ...values) {let i = -1;
function callback(exp, p0, p1, p2, p3, p4) {if (exp === '%%') return '%';if (values[++i] === undefined) return undefined;
exp = p2 ? parseInt(p2.substr(1)) : undefined;
let base = p3 ? parseInt(p3.substr(1)) : undefined;let val;
switch (p4) {case 's': val = values[i]; break;case 'c': val = values[i][0]; break;case 'f': val = parseFloat(values[i]).toFixed(exp); break;case 'p': val = parseFloat(values[i]).toPrecision(exp); break;case 'e': val = parseFloat(values[i]).toExponential(exp); break;case 'x': val = parseInt(values[i]).toString(base ? base : 16); break;case 'd': val = parseFloat(parseInt(values[i], base ? base : 10).toPrecision(exp)).toFixed(0); break;}val = typeof (val) == 'object' ? JSON.stringify(val) : val.toString(base);let sz = parseInt(p1); /* padding size */let ch = p1 && p1[0] === '0' ? '0' : ' '; /* isnull? */
while (val.length < sz) val = p0 !== undefined ? val + ch : ch + val; /* isminus? */
return val;}
let regex = /%(-)?(0?[0-9]+)?([.][0-9]+)?([#][0-9]+)?([scfpexd%])/g;
return template.replace(regex, callback);}
String.prototype.format = function() {return String.format(this, ...arguments);}
const StringFormat = {install: (Vue, options) => {Vue.filter('format', function () {return String.format(...arguments);});},};
export default StringFormat;

原答案:相当于printf/String. Format的JavaScript

如果您需要printf,请使用printf

看起来90%的评论者从未使用过比%d格式更复杂的printf。我想知道他们如何输出,例如,货币价值?

现在,有一个名为<强>洛削减我们的包,它将其他语言的函数翻译成Javascript,例如php、python、ruby等。

const printf = require('locutus/php/strings/printf')printf('Hello world');

你可以试试这个游乐场代码框

好的,首先我们设置一些要使用的变量:

    const date = new Date();    
const locale = 'en-us';    
const wDay   = date.toLocaleString(locale, {weekday: 'short'});const month  = date.toLocaleString(locale, {month: 'long'});const year   = date.toLocaleString(locale, {year: 'numeric'});const minute = date.toLocaleString(locale, {minute: 'numeric'});const [hour, ap] = date.toLocaleString(locale, {hour: 'numeric', hour12:true}).split(' ');    
let mDay = date.toLocaleString(locale, {day: 'numeric'});    
switch(mDay % 10){case 1:  mDay += 'st'; break;case 2:  mDay += 'nd'; break;case 3:  mDay += 'rd'; break;default: mDay += 'th'; break;}

现在我们已经得到了所有这些,我们可以像这样格式化一个字符串:

    const formatter = (...a) => `${a[0]}, the ${a[1]} of ${a[2]} ${a[3]} at ${a[4]}:${a[5]} ${a[6]}`;const formatted = formatter(wDay, mDay, month, year, hour, minute, ap);

我们甚至可以为“formatter”函数使用命名参数:

    const formatter = (wDay, mDay, month, year, hour, minute, ap) => `${wDay}, the ${mDay} of ${month} ${year} at ${hour}:${minute} ${ap}`;const formatted = formatter(wDay, mDay, month, year, hour, minute, ap);

如果你注意到,上面的JS模板都是回调的结果。如果上面的整段代码都封装在一个预期返回格式化日期的函数中,不难想象如何以同样的方式构造一个可以从外部传入的任意“格式化器”函数。

tl; dr如果您将模板文字放入回调并使用args作为替换,您可以重用它们。

3种不同的方式来格式化JavaScript字符串

通过用变量值替换占位符来格式化字符串有3种不同的方法。

  1. 使用模板文字(反引号")

    let name = 'John';let age = 30;// using backticksconsole.log(`${name} is ${age} years old.`);// John is 30 years old.

  2. 使用连接

let name = 'John';let age = 30;// using concatenationconsole.log(name + ' is ' + age + ' years old.');// John is 30 years old.

  1. 创建自己的格式函数

String.prototype.format = function () {var args = arguments;return this.replace(/{([0-9]+)}/g, function (match, index) {// check if the argument is therereturn typeof args[index] == 'undefined' ? match : args[index];});};

console.log('{0} is {1} years old.'.format('John', 30));

我使用模板文字方法,如下所示:

export const messages = {foo: (arg1, arg2) => `Hello ${arg1} ${arg2}`,bar: (arg1) => `Hello ${arg1}`,}

从文件:

console.log(messages.foo('Bar', 'World'))console.log(messages.bar('Foo'))

旧答案https://stackoverflow.com/a/18234317/19531844的修改代码效率更高(没有慢RegExp)并且更短

String.prototype.formatUnicorn = function () {let str = this.toString();if(!arguments.length) {return;};const [args] = arguments;for (const key of Object.keys(args)) {str = str.replaceAll(`{${key}}`, args[key]);};return str;};

用法:

"{test} {test_2} {test}".formatUnicorn({"test": "hello", "test_2": "world"}); // yields hello world hello

新旧之间的基准:https://jsben.ch/BRovx