13

I found a bug in my JavaScript code that I have isolated to a string replace that is acting in a way I didn't expect. Here is an example of the code:

var text = "as";
text = text.replace(text,"$\'");
console.log(text);

This prints an empty string to the console. I was expecting it to print $' to the console. Can anyone explain this?

johnnyRose
  • 7,310
  • 17
  • 40
  • 61
  • 2
    More information can be found in the specification: http://es5.github.com/#x15.5.4.11. As Alex mentioned in his deleted answer, `$'` is a special character sequence which gets replaced by the string following the match. E.g. `"foobar".replace("foo", "$'")` becomes `barbar`. – Felix Kling Feb 24 '12 at 00:45
  • See also [JavaScript replace() method dollar signs](https://stackoverflow.com/q/38866071/1048572) – Bergi Jan 16 '23 at 22:44

3 Answers3

22

In order to use $ in resulting string, use $$ as $ has special meaning in JavaScript Regular Expressions and String replace method: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#Specifying_a_string_as_a_parameter

Paul
  • 6,061
  • 6
  • 39
  • 70
Misha Reyzlin
  • 13,736
  • 4
  • 54
  • 63
  • If I use $$, will other browsers understand that I want '$' rather than accepting it as a '$$' string literal? edit: It looks like this is standard JavaScript. When I first asked the question about other browsers, it appeared to me that this was a quirk of Firefox. –  Feb 24 '12 at 00:54
  • this is standardized behavior and it works in IE too: http://msdn.microsoft.com/en-us/library/windows/apps/t0kbytzc(v=vs.94).aspx – Misha Reyzlin Feb 24 '12 at 00:56
  • 1
    Thanks. I was unclear on whether this was standard JavaScript or a quirk of Firefox. –  Feb 24 '12 at 00:57
  • Fwiw: Painfully, odd numbered strings of `$` can have their replacement `$`s "round up", so to speak. So (using Chrome), `"1,2,3,4".replace(/,/g, "$$$")` gives `"1$$2$$3$$4"`. That is, here, **one escaped `$` plus one unescaped (ie, `$$$`) acts likes two escaped (`$$$$`)!** Makes the two-for-one escape pattern a little more difficult to sniff. ;^) – ruffin Jan 04 '16 at 16:58
21

If I don't know what is in my replacement string I use

replaceWith = "might have 2 $ signs $$ $$$ $$$$"
"a b c".replace("b", replaceWith) // unexpected result
"a b c".replace("b", function(){return replaceWith}) // no surprises
Duppy
  • 361
  • 2
  • 5
  • 1
    this is so simple and so useful! thanks, spared me some trouble, i was beginning to think about how to escape all `$` with `$`.. using regexes? obviously not a good idea! – Kaddath Jul 05 '17 at 13:42
  • 2
    This trick actually just saved my butt potentially everywhere in one of my projects due to templating within localizable strings used throughout. It was a little too much hassle to sort out what `$`s are meant to be escaped if any are given from user input or whatever. So much easier just to throw `() =>` before the string and be done with it. – Zack Campbell Jul 06 '17 at 21:31
  • Best reply, no need to mess around with escaping. The exact string you want to be inserted as the replacement is what it gets – Omer Dec 14 '17 at 10:21
2

Actually, the most straight forward answer to this question is to use a function for the replacement string, because the w3c spec states that this result will not be affected by special characters.

var str = "abc {def} ghi";

console.log(str.replace("{def}", function() {
  return "foo$'bar"; 
}));

// result is
// "abc foo$'bar ghi"

The MDN documentation for that is here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace

Eric Rowell
  • 5,191
  • 23
  • 22