[javascript] Format a JavaScript string using placeholders and an object of substitutions?

I have a string with say: My Name is %NAME% and my age is %AGE%.

%XXX% are placeholders. We need to substitute values there from an object.

Object looks like: {"%NAME%":"Mike","%AGE%":"26","%EVENT%":"20"}

I need to parse the object and replace the string with corresponding values. So that final output will be:

My Name is Mike and my age is 26.

The whole thing has to be done either using pure javascript or jquery.

This question is related to javascript jquery string string-formatting

The answer is


You can use JQuery(jquery.validate.js) to make it work easily.

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

Or if you want to use just that feature you can define that function and just use it like

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

credit to jquery.validate.js team


How about using ES6 template literals?

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

More about template literals...


I have written a code that lets you format string easily.

Use this function.

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

Example

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

Output

My Name is Mike and my age is 26


As with modern browser, placeholder is supported by new version of Chrome / Firefox, similar as the C style function printf().

Placeholders:

  • %s String.
  • %d,%i Integer number.
  • %f Floating point number.
  • %o Object hyperlink.

e.g.

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

BTW, to see the output:

  • In Chrome, use shortcut Ctrl + Shift + J or F12 to open developer tool.
  • In Firefox, use shortcut Ctrl + Shift + K or F12 to open developer tool.

@Update - nodejs support

Seems nodejs don't support %f, instead, could use %d in nodejs. With %d number will be printed as floating number, not just integer.


Just use replace()

var values = {"%NAME%":"Mike","%AGE%":"26","%EVENT%":"20"};
var substitutedString = "My Name is %NAME% and my age is %AGE%.".replace("%NAME%", $values["%NAME%"]).replace("%AGE%", $values["%AGE%"]);

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

This allows you to do exactly that

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

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

By doing the following:

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

// My username is tjcafferkey on Git

You can use a custom replace function like this:

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

You can see it work here: http://jsfiddle.net/jfriend00/DyCwk/.


Here is another way of doing this by using es6 template literals dynamically at runtime.

_x000D_
_x000D_
const str = 'My name is ${name} and my age is ${age}.'_x000D_
const obj = {name:'Simon', age:'33'}_x000D_
_x000D_
_x000D_
const result = new Function('const {' + Object.keys(obj).join(',') + '} = this.obj;return `' + str + '`').call({obj})_x000D_
_x000D_
document.body.innerHTML = result
_x000D_
_x000D_
_x000D_


Currently there is still no native solution in Javascript for this behavior. Tagged templates are something related, but don't solve it.

Here there is a refactor of alex's solution with an object for replacements.

The solution uses arrow functions and a similar syntax for the placeholders as the native Javascript interpolation in template literals ({} instead of %%). Also there is no need to include delimiters (%) in the names of the replacements.

There are two flavors (three with the update): descriptive, reduced, elegant reduced with groups.

Descriptive solution:

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

Reduced solution:

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

UPDATE 2020-12-10

Elegant reduced solution with groups, as suggested by @Kade in the comments:

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

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

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

console.log(string);
_x000D_
_x000D_
_x000D_

UPDATE 2021-01-21

Support empty string as a replacement, as suggested by @Jesper in the comments:

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

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

const string = stringWithPlaceholders.replace(
  /{(\w+)}/g, 
  (placeholderWithDelimiters, placeholderWithoutDelimiters) =>
  replacements.hasOwnProperty(placeholderWithoutDelimiters) ? 
    replacements[placeholderWithoutDelimiters] : placeholderWithDelimiters
);

console.log(string);
_x000D_
_x000D_
_x000D_


If you want to do something closer to console.log like replacing %s placeholders like in

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

I wrote this

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

you will get

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

UPDATE

I have added a simple variant as String.prototype useful when dealing with string transformations, here is it:

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

In that case you will do

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

Try this version here


As a quick example:

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

The output is:

jack is 40 yrs old


Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to jquery

How to make a variable accessible outside a function? Jquery assiging class to th in a table Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Getting all files in directory with ajax Bootstrap 4 multiselect dropdown Cross-Origin Read Blocking (CORB) bootstrap 4 file input doesn't show the file name Jquery AJAX: No 'Access-Control-Allow-Origin' header is present on the requested resource how to remove json object key and value.?

Examples related to string

How to split a string in two and store it in a field String method cannot be found in a main class method Kotlin - How to correctly concatenate a String Replacing a character from a certain index Remove quotes from String in Python Detect whether a Python string is a number or a letter How does String substring work in Swift How does String.Index work in Swift swift 3.0 Data to String? How to parse JSON string in Typescript

Examples related to string-formatting

JavaScript Chart.js - Custom data formatting to display on tooltip Format in kotlin string templates Converting Float to Dollars and Cents Chart.js - Formatting Y axis String.Format not work in TypeScript Use StringFormat to add a string to a WPF XAML binding How to format number of decimal places in wpf using style/template? How to left align a fixed width string? Convert Java Date to UTC String Format a Go string without printing?