251
s = 'hello %s, how are you doing' % (my_name)

That's how you do it in python. How can you do that in javascript/node.js?

isherwood
  • 58,414
  • 16
  • 114
  • 157
TIMEX
  • 259,804
  • 351
  • 777
  • 1,080
  • 2
    I'm sure there was an es-next strawman somewhere for doing `var s = 'hello ${my_name}, how are you doing';` – Raynos Oct 17 '11 at 10:53
  • 1
    I use as Raynos said: const poem = "The black river"; const author = "Joseph Troll"; const favePoem = \`My favorite poem is ${poem} by ${author}\.`; Or you can use: console.log('%s is %d.', 'Eleven', 11); – Gilberto B. Terra Jr. Jan 29 '19 at 11:47
  • 3
    Normal templating is available for years now ***BUT YOU MUST USE BACKTICKS*** https://stackoverflow.com/a/37245773/294884 https://stackoverflow.com/a/37245773/294884 https://stackoverflow.com/a/37245773/294884 https://stackoverflow.com/a/37245773/294884 – Fattie Oct 21 '20 at 14:41
  • 1
    If you are stuck with `sprintf` formatting you can use `util.format('hello %s, how are you doing', my_name)` which still works in v14.15.4! see the docs https://nodejs.org/docs/latest/api/util.html#util_util_format_format_args – Steven de Salas Jan 25 '21 at 15:11

15 Answers15

489

With Node.js v4 , you can use ES6's Template strings

var my_name = 'John';
var s = `hello ${my_name}, how are you doing`;
console.log(s); // prints hello John, how are you doing

You need to wrap string within ` (backtick) instead of ' (apostrophe)

blackraven
  • 5,284
  • 7
  • 19
  • 45
Sridhar
  • 11,466
  • 5
  • 39
  • 43
  • 1
    Plus 1 Because we are in 2017 and ES6 is basically standard in the node world. – Jankapunkt May 10 '17 at 10:46
  • 1
    This is now (2017) the correct answer. Be aware that you will need Babel in your toolchain to support older browsers. – superluminary Sep 13 '17 at 08:17
  • 4
    I've suggested to the node.js developers that it would be really useful to make it clear on pages such as https://nodejs.org/api/readline.html that it is a backtick. There was an issue for it here: https://github.com/nodejs/docs/issues/55 – Gail Foad Sep 29 '17 at 19:55
  • 1
    Fell for the backticks trap myself, thanks for the comment ;) – Overdrivr Jan 24 '18 at 07:18
  • 3
    What if my string is a part of configuration file `hello ${my_name}, how are you doing` and I want to assign variable dynamically after reading string from config? – Amreesh Tyagi Jul 11 '18 at 15:39
  • @AmreeshTyagi note I'm not using backticks, in your config file `let cfgVal = "hello ${my_name}";` then you would use `let newVal = cfgVal.replace("${my_name}", someVal);` Though I would probably elect for a different marker to denote a config value so you don't conflict w. ES6 template strings. – jusopi Oct 18 '18 at 14:19
  • @Amreesh Tyagi use this function then https://stackoverflow.com/a/56958015/5263696 ;) – Fatih Turgut Jul 09 '19 at 17:54
  • The "backtick" tip helped me. – rodrigorf Oct 20 '19 at 19:24
  • but what if you need to load the string from a file? – john k May 13 '22 at 20:58
181

Note, from 2015 onwards, just use backticks for templating

let a = `hello ${name}`    // NOTE!!!!!!!! ` not ' or "

Note that it is a backtick, not a quote.


If you want to have something similar, you could create a function:

function parse(str) {
    var args = [].slice.call(arguments, 1),
        i = 0;

    return str.replace(/%s/g, () => args[i++]);
}

Usage:

s = parse('hello %s, how are you doing', my_name);

This is only a simple example and does not take into account different kinds of data types (like %i, etc) or escaping of %s. But I hope it gives you some idea. I'm pretty sure there are also libraries out there which provide a function like this.

Cadoiz
  • 1,446
  • 21
  • 31
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • 2
    That's basically the best you'll get since it's not supported directly by the language as it is in python. – Joseph Yaduvanshi Oct 18 '11 at 17:20
  • 1
    The other answer, that features util.format(), should be the accepted answer... though preferably it would also mention ES6's template strings (which admittedly didn't exist in 2011). We really should be able to wiki-hijack old questions to keep them updated. :\ – Kyle Baker Jun 21 '16 at 16:03
  • 1
    This is nice, the template literals aren't exactly same thing – Capuchin Mar 07 '17 at 16:31
  • I had an issue while using "arguments". When multiple clients passed from the parse, the "str" was mixed up. Any explanation? – tspentzas Nov 30 '18 at 08:42
  • @tspentzas: I don't know what *"When multiple clients passed from the parse"* is supposed to mean. – Felix Kling Nov 30 '18 at 09:02
  • is parse running synchronously? – tspentzas Nov 30 '18 at 09:11
  • @tspentzas: Yes. And even if it didn't, JavaScript never executes code *concurrently* (i.e. multiple at the same time). – Felix Kling Nov 30 '18 at 09:11
63

if you are using ES6, the you should use the Template literals.

//you can do this
let sentence = `My name is ${ user.name }. Nice to meet you.`

read more here.

Cadoiz
  • 1,446
  • 21
  • 31
Terrence
  • 2,189
  • 1
  • 15
  • 12
48

util.format does this.

It will be part of v0.5.3 and can be used like this:

var uri = util.format('http%s://%s%s', 
      (useSSL?'s':''), apiBase, path||'/');
Joseph Yaduvanshi
  • 20,241
  • 5
  • 61
  • 69
45

As of node.js >4.0 it gets more compatible with ES6 standard, where string manipulation greatly improved.

The answer to the original question can be as simple as:

var s = `hello ${my_name}, how are you doing`;
// note: tilt ` instead of single quote '

Where the string can spread multiple lines, it makes templates or HTML/XML processes quite easy. More details and more capabilitie about it: Template literals are string literals at mozilla.org.

Andrew_1510
  • 12,258
  • 9
  • 51
  • 52
25

Do that:

s = 'hello ' + my_name + ', how are you doing'

Update

With ES6, you could also do this:

s = `hello ${my_name}, how are you doing`
KodeFor.Me
  • 13,069
  • 27
  • 98
  • 166
  • What do you mean "Its not possible" ? :? If you like to have formated text you can do it as described above by Felix Kling. This is the best answer as I see here ;) :) – KodeFor.Me Oct 17 '11 at 08:03
  • @TIMEX It's possible just give it a try. – dev_khan Jan 02 '18 at 13:06
7

I wrote a function which solves the problem precisely.

First argument is the string that wanted to be parameterized. You should put your variables in this string like this format "%s1, %s2, ... %s12".

Other arguments are the parameters respectively for that string.

/***
 * @example parameterizedString("my name is %s1 and surname is %s2", "John", "Doe");
 * @return "my name is John and surname is Doe"
 *
 * @firstArgument {String} like "my name is %s1 and surname is %s2"
 * @otherArguments {String | Number}
 * @returns {String}
 */
const parameterizedString = (...args) => {
  const str = args[0];
  const params = args.filter((arg, index) => index !== 0);
  if (!str) return "";
  return str.replace(/%s[0-9]+/g, matchedStr => {
    const variableIndex = matchedStr.replace("%s", "") - 1;
    return params[variableIndex];
  });
}

Examples

parameterizedString("my name is %s1 and surname is %s2", "John", "Doe");
// returns "my name is John and surname is Doe"

parameterizedString("this%s1 %s2 %s3", " method", "sooo", "goood");
// returns "this method sooo goood"

If variable position changes in that string, this function supports it too without changing the function parameters.

parameterizedString("i have %s2 %s1 and %s4 %s3.", "books", 5, "pencils", "6");
// returns "i have 5 books and 6 pencils."
Fatih Turgut
  • 319
  • 3
  • 9
5

A few ways to extend String.prototype, or use ES2015 template literals.

var result = document.querySelector('#result');
// -----------------------------------------------------------------------------------
// Classic
String.prototype.format = String.prototype.format ||
  function () {
    var args = Array.prototype.slice.call(arguments);
    var replacer = function (a){return args[a.substr(1)-1];};
    return this.replace(/(\$\d+)/gm, replacer)
};
result.textContent = 
  'hello $1, $2'.format('[world]', '[how are you?]');

// ES2015#1
'use strict'
String.prototype.format2 = String.prototype.format2 ||
  function(...merge) { return this.replace(/\$\d+/g, r => merge[r.slice(1)-1]); };
result.textContent += '\nHi there $1, $2'.format2('[sir]', '[I\'m fine, thnx]');

// ES2015#2: template literal
var merge = ['[good]', '[know]'];
result.textContent += `\nOk, ${merge[0]} to ${merge[1]}`;
<pre id="result"></pre>
KooiInc
  • 119,216
  • 31
  • 141
  • 177
4
var print = console.log;

function dformat(str, ...arr) {
  return str.replace(/%(\d+)/g, function(_,i) {
    return arr[--i];
  });
}

function wformat(str, dict) {
  return str.replace(/%(\w+)/g, function(_,k) {
    return dict[k];
  });
}

function sformat(str, dict) {
  return str.replace(/\$(\w+)/g, function(_,m) {
    return dict[m];
  });
}

function tformat(str, dict) {
  return str.replace(/\${(\w+)}/g, function(_,m) {
    return dict[m];
  });
}

print(1, dformat("uid:%1, name:%2", 120, "someone") )
print(2, wformat("color: %name", {name: "green"})   )
print(3, sformat("img: $url", {url: "#"})   )
print(4, tformat("${left} ${right}", {right:"1000", left: "7fff"}) )
leo
  • 49
  • 2
4

Try sprintf in JS or you could use this gist

spicavigo
  • 4,116
  • 22
  • 28
4

If you are using node.js, console.log() takes format string as a first parameter:

 console.log('count: %d', count);
Andrey Sidorov
  • 24,905
  • 4
  • 62
  • 75
  • This is a good point, but the question is about string interpolation. `console.log()` only outputs the formatted string to `STDOUT`. In other words, you can't use the result of `count: %d` – Joseph Yaduvanshi Oct 21 '11 at 20:48
  • FYI 2021 and this syntax is still very much supported! – JΛYDΞV May 04 '21 at 03:50
  • @JimSchubert This is sorta string interpolation, it just has a very specific use case. I feel that, because the user asked for this syntax specifically, it was worth mentioning in an answer. – JΛYDΞV May 04 '21 at 03:50
  • @NodeSamurai the question is how to put variables into strings. The console.log answer just shows how console.log supports string formatting as parameters, which may or may not work the same as other answers to the question. – Joseph Yaduvanshi May 08 '21 at 19:37
3

const format = (...args) => args.shift().replace(/%([jsd])/g, x => x === '%j' ? JSON.stringify(args.shift()) : args.shift())

const name = 'Csaba'
const formatted = format('Hi %s, today is %s and your data is %j', name, Date(), {data: {country: 'Hungary', city: 'Budapest'}})

console.log(formatted)
cstuncsik
  • 2,698
  • 2
  • 16
  • 20
2
var user = "your name";
var s = 'hello ' + user + ', how are you doing';
Termi
  • 435
  • 6
  • 18
  • I see a couple of problems with that; it uses concatenation rather than string formatting which is a red flag for me when doing code reviews, as it's usually more difficult to read and maintain. Also you can't safely store that "pattern" in a retrieval system (like a config file or DB) and inject in the value of user later. – Rory Browne Apr 29 '20 at 11:24
1

Here is a Multi-line String Literal example in Node.js.

> let name = 'Fred'
> tm = `Dear ${name},
... This is to inform you, ${name}, that you are
... IN VIOLATION of Penal Code 64.302-4.
... Surrender yourself IMMEDIATELY!
... THIS MEANS YOU, ${name}!!!
...
... `
'Dear Fred,\nThis is to inform you, Fred, that you are\nIN VIOLATION of Penal Code 64.302-4.\nSurrender yourself IMMEDIATELY!\nTHIS MEANS YOU, Fred!!!\n\n'
console.log(tm)
Dear Fred,
This is to inform you, Fred, that you are
IN VIOLATION of Penal Code 64.302-4.
Surrender yourself IMMEDIATELY!
THIS MEANS YOU, Fred!!!


undefined
>
0

You can implement your own format function that takes a string and key-value pairs.

the function:

function format(str, args) {
    return str.replace(/%(\w+)/g, (_, key) => args[key]);
}
const message = "Hello, %name! How are you doing?";
const args = {
    name: "Alice"
};

const formattedMessage= format(message, args);
Ahmed Hany
  • 952
  • 6
  • 12