6

I'm struggling to get an ES6 template literal to produce a single backslash it its result.

> `\s`
's'
> `\\s`
'\\s'
> `\\\s`
'\\s'
> `\\\\s`
'\\\\s'
> `\u005Cs`
'\\s'

Tested with Node 8.9.1 and 10.0.0 by inspecting the value at a Node REPL (rather than printing it using console.log)

brabster
  • 42,504
  • 27
  • 146
  • 186
  • Same as every other string literal. `\`\\\` === "\\"`. It's just the REPL representation that is confusing you. – Bergi Apr 25 '18 at 18:13

2 Answers2

4

It is a known issue that unknown string escape sequences lose their escaping backslash in JavaScript normal and template string literals:

When a character in a string literal or regular expression literal is preceded by a backslash, it is interpreted as part of an escape sequence. For example, the escape sequence \n in a string literal corresponds to a single newline character, and not the \ and n characters. However, not all characters change meaning when used in an escape sequence. In this case, the backslash just makes the character appear to mean something else, and the backslash actually has no effect. For example, the escape sequence \k in a string literal just means k. Such superfluous escape sequences are usually benign, and do not change the behavior of the program.

In regular string literals, one needs to double the backslash in order to introduce a literal backslash char:

console.log("\s \\s"); // => s \s
console.log('\s \\s'); // => s \s
console.log(`\s \\s`); // => s \s

There is a better idea: use String.raw:

The static String.raw() method is a tag function of template literals. This is similar to the r prefix in Python, or the @ prefix in C# for string literals. (But it is not identical; see explanations in this issue.) It's used to get the raw string form of template strings, that is, substitutions (e.g. ${foo}) are processed, but escapes (e.g. \n) are not.

So, you may simply use String.raw`\s` to define a \s text:

console.log(String.raw`s \s \\s`); // => s \s \\s
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • 2
    `String.raw` did it for me, thanks! – omerts Jul 21 '22 at 08:52
  • [MDN link for `String.raw`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/raw) (aka, if you were wondering, it is legit/baked in/[vanilla at some point](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/raw#browser_compatibility), which was implied, but not made explicit, in this answer.) – ruffin Jan 11 '23 at 21:06
3

If I get your question right, how about \\?

I tried using $ node -i and run

console.log(`\\`);

Which successfully output a backslash. Keep in mind that the output might be escaped as well, so the only way to know you are successfully getting a backslash is getting the character code:

const myBackslash = `\\`;
console.log(myBackslash.charCodeAt(0)); // 92

And to make sure you are not actually getting \\ (i.e. a double-backslash), check the length:

console.log(myBackslash.length); // 1
Victor
  • 13,914
  • 19
  • 78
  • 147
  • I *think* that it's the console.log function that's doing the interpretation of the first backslash as an escape char there, rather than the template literal... but I'm not sure that'll work for me as I'm using it to create a regex in a SQL statement (don't ask why!). – brabster Apr 25 '18 at 16:17
  • I was testing at a node repl, just evaluating those template strings and looking at the resulting value, rather than printing the output – brabster Apr 25 '18 at 16:18
  • Keep in mind that the output of a `console.log` or the output of REPL will be escaped as well. Please see [this example on Runkit](https://runkit.com/barbu110/backslash-out-of-a-template-string) – Victor Apr 25 '18 at 16:25
  • Aha! Didn't think about the REPL escaping, that's it! Calling `length` on the results also shows they are actually a different length than they appear when you've got multiple sequential `\` chars – brabster Apr 25 '18 at 16:32
  • Glad I could be of use! – Victor Apr 25 '18 at 16:36