etc./StackOverFlow

printf/String.Format에 해당하는 JavaScript

청렴결백한 만능 재주꾼 2021. 12. 3. 08:21
반응형

질문자 :Community Wiki


printf() 또는 C#/Java 프로그래머의 경우 String.Format() (.NET의 경우 IFormatProvider )에 해당하는 우수한 JavaScript를 찾고 있습니다.

내 기본 요구 사항은 현재 숫자에 대한 천 단위 구분 기호 형식이지만 많은 조합(날짜 포함)을 처리하는 것이 좋습니다.

Microsoft의 Ajax String.Format() 버전을 제공한다는 것을 알고 있지만 해당 프레임워크의 전체 오버헤드를 원하지 않습니다.



이전에 제안된 솔루션을 기반으로 구축:

 // 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은 살아 있습니다! ASP {2}


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은 살아 있습니다! ASP {2}


fearphage

현재 자바스크립트

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} 입니다. 따라서 fearphage의 제안 과 같이 동시에 교체를 수행하십시오.


Community Wiki

formatUnicorn String 프로토타입에 대한 자체 서식 지정 기능이 있기 때문에 재미있습니다. 시도 해봐! 콘솔로 이동하여 다음과 같이 입력합니다.

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

개똥 벌레

다음과 같은 결과가 나타납니다.

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#의 String.Format 동작이 거의 정확하게 나타납니다.

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

그 이유는 Arrayslice 는 그것이 원래 있었는지 여부에 관계없이 arguments 에 있는 Array key 는 문자열로 강제 변환된 각 배열 요소의 인덱스(0, 1, 2...)가 되기 때문입니다(예: "0", 첫 번째 정규 표현식 패턴의 경우 "\\{0\\}"

정돈 된.


Community Wiki

JavaScript의 숫자 서식

다른 라이브러리를 도입하지 않고 JavaScript에서 숫자 형식을 지정 하는 방법을 찾기 위해 이 질문 페이지에 왔습니다. 내가 찾은 것은 다음과 같습니다.

부동 소수점 숫자 반올림

JavaScript의 sprintf("%.2f", num) num.toFixed(2) 보입니다. num 을 소수점 이하 2자리로 지정합니다(그러나 Math.round 에 대한 @ars265의 설명 참조).

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

16진수 및 기타 기수

기본 B의 숫자를 인쇄하려면 num.toString(B) 시도하십시오. JavaScript는 base 2에서 36까지의 자동 변환을 지원합니다(또한 일부 브라우저는 base64 인코딩에 대한 지원 이 제한적임).

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

참조 페이지

JS 숫자 형식에 대한 빠른 자습서

toFixed()에 대한 Mozilla 참조 페이지( toPrecision(), toExponential(), toLocaleString(), ...에 대한 링크 포함)


Community Wiki

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 사이트를 확인하십시오.


Community Wiki

jsxt, 지포

이 옵션이 더 적합합니다.

 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}는 대체되지 않습니다. ;)


Community Wiki

이 간단한 기능을 사용합니다.

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

Community Wiki

Node.js 사용자의 경우 printf와 유사한 기능 util.format

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

Community Wiki

reduce 사용하지 않았다는 사실에 놀랐습니다. 이것은 간결하고 강력한 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'));

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

작동 방식:

reduce 는 누산기와 배열의 각 요소(왼쪽에서 오른쪽으로)에 대해 함수를 적용하여 단일 값으로 줄입니다.

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


Community Wiki

다음 은 JavaScript에서 sprintf를 최소한으로 구현한 것입니다. "%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, eg %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; }); }

예시:

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

이전 답변의 유사한 솔루션과 달리 이 솔루션은 모든 대체 를 한 번 에 수행하므로 이전에 대체된 값의 일부를 대체하지 않습니다.


Community Wiki

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

Community Wiki

zippoxer 의 답변에 추가하여 다음 기능을 사용합니다.

 String.prototype.format = function () { var a = this, b; for (b in arguments) { a = a.replace(/%[az]/, 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(/%[az]/, b[c]); } return a; } format('%d ducks, 55 %s', 12, 'cats'); // 12 ducks, 55 cats

ES 2015 업데이트

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! %%"

Community Wiki

'문제'에 대한 솔루션을 공유하고 싶습니다. 바퀴를 다시 발명하지는 않았지만 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'

Community Wiki

+1 Zippo를 제외하고 함수 본문은 아래와 같아야 하며 그렇지 않으면 모든 반복에서 현재 문자열을 추가합니다.

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

Community Wiki

내가 질문한 이후에 발견한 내 자신의 발견을 추가하겠습니다.

슬프게도 sprintf는 .NET의 문자열 형식과 같은 천 단위 구분 기호 형식을 처리하지 않는 것 같습니다.


Community Wiki

대부분의 형식 문자열 기능(숫자 및 날짜 형식 포함)을 지원하고 .NET 구문을 사용하는 JavaScript용 String.format 이라는 작은 라이브러리를 사용합니다. 스크립트 자체는 4kB보다 작기 때문에 많은 오버헤드를 생성하지 않습니다.


Community Wiki

매우 우아한:

 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


Community Wiki

천 단위 구분 기호를 처리하려면 JavaScript Number 클래스에서 toLocaleString()을 사용해야 합니다. 사용자 지역에 대한 문자열 형식을 지정하기 때문입니다.

JavaScript Date 클래스는 현지화된 날짜 및 시간의 형식을 지정할 수 있습니다.


Community Wiki

http://www.webtoolkit.info/javascript-sprintf.html 에서 찾을 수 있는 JavaScript용 "sprintf"가 있습니다.


Community Wiki

PHPJS 프로젝트 는 많은 PHP 기능에 대한 JavaScript 구현을 작성했습니다. PHP의 sprintf() 함수는 기본적으로 C의 printf() 와 동일하기 때문에 JavaScript 구현이 여러분의 요구를 만족시켜야 합니다.


Community Wiki

나는 이것을 사용한다:

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

Community Wiki

나는 Peter 's에 매우 가까운 솔루션을 가지고 있지만 숫자와 개체 사례를 다룹니다.

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

추신: 이 기능은 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." }

Community Wiki

아주 약간 다른 버전, 내가 선호하는 버전(이 버전은 번호가 매겨진 {0} 인수보다 {xxx} 토큰을 사용합니다. 이것은 훨씬 더 자체 문서화되고 현지화에 훨씬 더 적합합니다):

 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() 현지화 함수를 호출합니다.


Community Wiki

기본 서식의 경우:

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

Community Wiki

여기 에 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(저는 해당 라이브러리를 싫어함)) 감지 기능을 갖추고 있습니다.


Community Wiki

누군가가 전역 범위를 오염시키는 것을 방지하는 기능이 필요한 경우를 대비하여 다음과 같은 기능을 수행합니다.

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

Community Wiki

Node.JSutil.format 기능을 좋아하는 사람들을 위해 바닐라 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 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; };

출처: https://github.com/joyent/node/blob/master/lib/util.js


Community Wiki

Typescript에 간단한 경량 String.Format 문자열 작업 라이브러리를 사용할 수 있습니다.

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

Community Wiki

목록에 pyformat 이 표시되지 않아 다음과 같이 입력할 것이라고 생각했습니다.

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

Community Wiki

Lodash 를 사용하면 템플릿 기능을 얻을 수 있습니다.

ES 템플릿 리터럴 구분 기호를 "보간" 구분 기호로 사용합니다. "보간" 구분 기호를 교체하여 지원을 비활성화합니다.

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

Community Wiki

출처 : http:www.stackoverflow.com/questions/610406/javascript-equivalent-to-printf-string-format

반응형