자리 표시 자와 대체 개체를 사용하여 JavaScript 문자열 형식을 지정 하시겠습니까?


92

다음과 같은 문자열이 있습니다. My Name is %NAME% and my age is %AGE%.

%XXX%자리 표시 자입니다. 객체에서 값을 대체해야합니다.

개체는 다음과 같습니다. {"%NAME%":"Mike","%AGE%":"26","%EVENT%":"20"}

개체를 구문 분석하고 문자열을 해당 값으로 바꿔야합니다. 따라서 최종 출력은 다음과 같습니다.

제 이름은 Mike이고 나이는 26 세입니다.

모든 작업은 순수 자바 스크립트 또는 jquery를 사용하여 수행해야합니다.


2
그것은 배열 이라기보다는 객체처럼 보입니다
Joel Coehoorn 2011

3
지금까지 뭐 해봤 어? 문자열 .replace () 메서드를 보셨습니까 ? (또한 거기에 배열이없고 객체가 있습니다.)
nnnnnn

1
그것은 꽤 추합니다. 확실히 당신은 잘 봉사 할 것 {NAME: "Mike", AGE: 26, EVENT: 20}입니까? 물론 이러한 키는 입력 문자열에서 백분율 기호로 예약되어 표시되어야합니다.
davidchambers 2011

답변:


153

원래 질문의 요구 사항은 임의의 대체 키의 런타임 처리처럼 보이기 때문에 문자열 보간의 이점을 얻을 수 없었습니다.

그러나 문자열 보간 만 수행해야하는 경우 다음을 사용할 수 있습니다.

const str = `My name is ${replacements.name} and my age is ${replacements.age}.`

문자열을 구분하는 백틱은 필수입니다.


특정 OP의 요구 사항에 맞는 답변을 얻으 String.prototype.replace()려면 교체에 사용할 수 있습니다 .

다음 코드는 모든 일치 항목을 처리하고 교체하지 않은 항목은 터치하지 않습니다 (교체 값이 모두 문자열 인 경우 아래 참조).

var replacements = {"%NAME%":"Mike","%AGE%":"26","%EVENT%":"20"},
    str = 'My Name is %NAME% and my age is %AGE%.';

str = str.replace(/%\w+%/g, function(all) {
   return replacements[all] || all;
});

jsFiddle .

대체 항목 중 일부가 문자열이 아닌 경우 먼저 개체에 있는지 확인하십시오. 예와 같은 형식이있는 경우 (예 : 백분율 기호로 래핑) in연산자를 사용하여 이를 수행 할 수 있습니다 .

jsFiddle .

그러나 형식에 특수 형식 (예 : 문자열)이없고 교체 객체에 null프로토 타입 이없는 경우 Object.prototype.hasOwnProperty()잠재적으로 교체 된 하위 문자열이 프로토 타입의 속성 이름과 충돌하지 않는다고 보장 할 수없는 경우를 사용 합니다.

jsFiddle .

그렇지 않으면 대체 문자열이 'hasOwnProperty'이면 결과적으로 엉망인 문자열이 표시됩니다.

jsFiddle .


보조 노트로서, 당신은 호출해야 replacementsObject아닌가 Array.


2
+1. 좋은. 사건 return replacements[all] || all을 다루 라고 말하고 싶을 수도 있습니다 %NotInReplacementsList%.
nnnnnn

6
대체 값이 거짓이면 작동하지 않습니다. : 그것은이 return 문을 사용하는 것이 좋습니다 그래서return all in params ? params[all] : all;
마이클 하틀

@ MichaelHärtl 대체물이 모두 문자열이어야하지 않습니까? 빈 문자열로 바꾸려면 다른 방법으로 확인하는 것이 좋습니다.
알렉스

1
@alex 나는 대체물이 정수일 수도 있고 심지어 0. 이 경우에는 작동하지 않았습니다.
Michael Härtl

@ MichaelHärtl이 경우를 다루기 위해 업데이트되었습니다.
alex

24

ES6 템플릿 리터럴을 사용하는 것은 어떻습니까?

var a = "cat";
var b = "fat";
console.log(`my ${a} is ${b}`); //notice back-ticked string

템플릿 리터럴에 대한 추가 정보 ...


5
OP와 같은 자리 표시자가있는 개체가있는 경우 문자열 보간이 어떻게 도움이됩니까?
alex

매력처럼 작동합니다! 내 자리 잡기 문제에 대한 가장 실용적인 해결책은 완벽합니다.
BAERUS

이 솔루션은 런타임 교체에는 작동하지 않습니다
Thierry J.

13

JQuery (jquery.validate.js)를 사용하여 쉽게 작동 할 수 있습니다.

$.validator.format("My name is {0}, I'm {1} years old",["Bob","23"]);

또는 해당 기능 만 사용하려는 경우 해당 기능을 정의하고 다음과 같이 사용할 수 있습니다.

function format(source, params) {
    $.each(params,function (i, n) {
        source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n);
    })
    return source;
}
alert(format("{0} is a {1}", ["Michael", "Guy"]));

jquery.validate.js 팀에 대한 크레딧


1
이 플러그인을로드하고 싶지는 않지만 이미 페이지에서 양식의 유효성을 검사하는 데이 플러그인을 사용하고 있습니다. 팁을 주셔서 감사합니다!
nabrown

1
각 숫자에 대한 정규식을 만드는 것은 매우 비효율적입니다. 모든 숫자를 일치시킨 다음 값이 배열에서 발견되면 대체하는 것이 좋습니다.
alex

관심있는 사람을 위해, 여기 발생합니다 github.com/jquery-validation/jquery-validation/blob/master/src/...
라파엘 C

1
+ 아주 좋은 ... 그리고 대한 $.each당신이 만들 수있는 String.prototype.format=function(p){var s=this,r=function(v,i){s=s.replace(new RegExp("\\{"+i+"\\}","g"),v);};p.forEach(r);return s;}당신은 단지 하나 JQuery와 포함 할 필요가 없습니다)
Larphoid

11

최신 브라우저와 마찬가지로 자리 표시자는 C 스타일 기능과 유사한 새 버전의 Chrome / Firefox에서 지원됩니다 printf().

자리 표시 자 :

  • %s 끈.
  • %d, %i정수.
  • %f 부동 소수점 수.
  • %o 개체 하이퍼 링크.

console.log("generation 0:\t%f, %f, %f", a1a1, a1a2, a2a2);

BTW, 출력을 보려면 :

  • Chrome에서 바로 가기를 사용 Ctrl + Shift + J하거나 F12개발자 도구를 엽니 다.
  • Firefox에서는 바로 가기를 사용 Ctrl + Shift + K하거나 F12개발자 도구를 엽니 다.

@Update-nodejs 지원

nodejs는을 지원하지 않고 %f대신 %dnodejs에서 사용할 수 있습니다 . 함께 %d숫자뿐만 아니라 정수, 부동 숫자로 인쇄됩니다.



5

다음과 같은 사용자 지정 바꾸기 기능을 사용할 수 있습니다.

var str = "My Name is %NAME% and my age is %AGE%.";
var replaceData = {"%NAME%":"Mike","%AGE%":"26","%EVENT%":"20"};

function substitute(str, data) {
    var output = str.replace(/%[^%]+%/g, function(match) {
        if (match in data) {
            return(data[match]);
        } else {
            return("");
        }
    });
    return(output);
}

var output = substitute(str, replaceData);

http://jsfiddle.net/jfriend00/DyCwk/에서 작동하는 것을 볼 수 있습니다 .


1
멋지다. Alex는 거의 똑같은 작업을 수행했지만 코드 줄 수가 적습니다 (삼항 연산자가 if..else보다 느릴 가능성이 있음).
RobG 2011

이봐, 내가 너에게 +1을 줬어! 둘 다 대체 기능을 수행했지만 정확히 동일하지는 않지만 매우 유사합니다. RegExp도 다릅니다. OP는 %% 또는 $$ 또는 구분 기호로 유사한 것을 사용하는 것이 더 낫습니다. 단일 % 또는 %는 일반적으로 문자열에서 발생할 가능성이 있지만 두 배는 발생하지 않습니다.
RobG 2011

4

% s 자리 표시자를 바꾸는 것과 같이 console.log에 더 가까운 작업을 수행하려면

>console.log("Hello %s how are you %s is everything %s?", "Loreto", "today", "allright")
>Hello Loreto how are you today is everything allright?

나는 이것을 썼다

function log() {
  var args = Array.prototype.slice.call(arguments);
  var rep= args.slice(1, args.length);
  var i=0;
  var output = args[0].replace(/%s/g, function(match,idx) {
    var subst=rep.slice(i, ++i);
    return( subst );
  });
   return(output);
}
res=log("Hello %s how are you %s is everything %s?", "Loreto", "today", "allright");
document.getElementById("console").innerHTML=res;
<span id="console"/>

당신은 얻을 것이다

>log("Hello %s how are you %s is everything %s?", "Loreto", "today", "allright")
>"Hello Loreto how are you today is everything allright?"

최신 정보

String.prototype문자열 변환을 다룰 때 유용한 간단한 변형을 추가 했습니다. 다음은 다음과 같습니다.

String.prototype.log = function() {
    var args = Array.prototype.slice.call(arguments);
    var rep= args.slice(0, args.length);
    var i=0;
    var output = this.replace(/%s|%d|%f|%@/g, function(match,idx) {
      var subst=rep.slice(i, ++i);
      return( subst );
    });
    return output;
   }

이 경우 당신은 할 것입니다

"Hello %s how are you %s is everything %s?".log("Loreto", "today", "allright")
"Hello Loreto how are you today is everything allright?"

여기 에서이 버전을 사용해보세요


2
프로토 타입없이 함수에 변형을 만들었습니다. formatMessage(message: string, values: string[]) { let i = 0; return message.replace(/%\w+%/g, (match, idx) => { return values[i++]; }); } 이것은 메시지를 형식화하고 교체 값의 배열로 가져 와서 찾습니다%SOME_VALUE%
baku

4

현재 Javascript에는이 동작에 대한 기본 솔루션이 아직 없습니다. 태그가 지정된 템플릿 은 관련이 있지만 해결하지 마십시오.

여기 에 대체 용 객체 로 alex의 솔루션 리팩터링이 있습니다.

이 솔루션은 템플릿 리터럴 ( 대신 ) 의 네이티브 자바 스크립트 보간 으로 자리 표시 자에 화살표 함수 와 유사한 구문을 사용합니다 . 또한 대체 이름에 구분 기호 ( ) 를 포함 할 필요없습니다 .{}%%%

설명과 축소의 두 가지 유형이 있습니다.

설명 솔루션 :

const stringWithPlaceholders = 'My Name is {name} and my age is {age}.';

const replacements = {
  name: 'Mike',
  age: '26',
};

const string = stringWithPlaceholders.replace(
  /{\w+}/g,
  placeholderWithDelimiters => {
    const placeholderWithoutDelimiters = placeholderWithDelimiters.substring(
      1,
      placeholderWithDelimiters.length - 1,
    );
    const stringReplacement = replacements[placeholderWithoutDelimiters] || placeholderWithDelimiters;
    return stringReplacement;
  },
);

console.log(string);

감소 된 솔루션 :

const stringWithPlaceholders = 'My Name is {name} and my age is {age}.';

const replacements = {
  name: 'Mike',
  age: '26',
};

const string = stringWithPlaceholders.replace(/{\w+}/g, placeholder =>
  replacements[placeholder.substring(1, placeholder.length - 1)] || placeholder,
);

console.log(string);


1
이 주셔서 감사합니다, 그것은 자리 문자열에 대한 일반적인 솔루션과 같은 그것에 병합에 객체 가지고 좋아요
카를로스 P

@CarlosP, 그것이 일반적인 솔루션을 갖는 아이디어입니다. 그러나 일반적인 사용 사례이므로 언어 ​​고유의 것이되어야한다고 생각합니다.
AMS777

1
다음과 같은 정규식 그룹을 사용하여 좀 더 단순화 할 수 있습니다.stringWithPlaceholders.replace(/{(\w+)}/g, (fullMatch, group1) => replacements[group1] || fullMatch )
Kade

2

이를 통해 정확하게 할 수 있습니다.

NPM : https://www.npmjs.com/package/stringinject

GitHub : https://github.com/tjcafferkey/stringinject

다음을 수행합니다.

var str = stringInject("My username is {username} on {platform}", { username: "tjcafferkey", platform: "GitHub" });

// My username is tjcafferkey on Git

2
그러나 es6에서 할 수 있기 때문에 아마도 약간 과잉일까요?
IonicBurger

1
이렇게하면 문자열을 한 형식으로 한 곳에 저장 한 다음 나중에 하나의 함수 만 사용하여 해당 항목을 바꿀 수 있습니다. 그것은 내가 아는 한 es6 템플릿 리터럴로는 불가능합니다. 예를 들어 다른 곳에서 문자열을 소비하고 원하는 값을 거기에 삽입하는 번역 문자열이 사용됩니다.
Johan Persson

2

다음은 런타임에 동적으로 es6 템플릿 리터럴을 사용하는 또 다른 방법입니다.

const str = 'My name is ${name} and my age is ${age}.'
const obj = {name:'Simon', age:'33'}


const result = new Function('const {' + Object.keys(obj).join(',') + '} = this.obj;return `' + str + '`').call({obj})

document.body.innerHTML = result


1

간단한 예로서 :

var name = 'jack';
var age = 40;
console.log('%s is %d yrs old',name,age);

출력은 다음과 같습니다.

잭은 40 세입니다.


7
콘솔에 기록하는 것 외에 다른 작업을하고 싶지 않다면 훌륭합니다.
alex

13
그게 아니야 console.log?
drzaus

0
const stringInject = (str = '', obj = {}) => {
  let newStr = str;
  Object.keys(obj).forEach((key) => {
    let placeHolder = `#${key}#`;
    if(newStr.includes(placeHolder)) {
      newStr = newStr.replace(placeHolder, obj[key] || " ");
    }
  });
  return newStr;
}
Input: stringInject("Hi #name#, How are you?", {name: "Ram"});
Output: "Hi Ram, How are you?"

0

문자열을 쉽게 포맷 할 수있는 코드를 작성했습니다.

이 기능을 사용하십시오.

function format() {
    if (arguments.length === 0) {
        throw "No arguments";
    }
    const string = arguments[0];
    const lst = string.split("{}");
    if (lst.length !== arguments.length) {
        throw "Placeholder format mismatched";
    }
    let string2 = "";
    let off = 1;
    for (let i = 0; i < lst.length; i++) {
        if (off < arguments.length) {
            string2 += lst[i] + arguments[off++]
        } else {
            string2 += lst[i]
        }
    }
    return string2;
}

format('My Name is {} and my age is {}', 'Mike', 26);

산출

제 이름은 Mike이고 나이는 26 세입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.