Refactor variable names in JavaScript code Your challenge today is to refactor JavaScript code. You will take three strings as input; a JavaScript string, a old variable name, and the name you want to refactor it to. For example, an input of

"var x = 100; alert(x);", "x", "num"


Will output

"var num = 100; alert(num);"




Here's a more advanced test case:

"var gb = 1; var g = bg = 2; gb = bg = g = function(gg) { alert(gb); };
var str = 'g gb bg gg'; var regexp = /gb gb gb/g; //comment gb gb g g
/*gb gb g g*/", "gb", "aaa"


It should output

var aaa = 1; var g = bg = 2; aaa = bg = g = function(gg) { alert(aaa); };
var str = 'g gb bg gg'; var regexp = /gb gb g g/g; //comment gb gb g g
/*gb gb g g*/


And the same JS input with the other arguments "g", "aaa" should output

var gb = 1; var aaa = bg = 2; gb = bg = aaa = function(gg) { alert(gb); };
var str = 'g gb bg gg'; var regexp = /gb gb gb/g; //comment gb gb g g
/*gb gb g g*/




Here is one last much more complicated test case:

var g = 1; "g\"g"; "g'"; g; '"g\'g"g'; /g"\/*\//g; g; "// /*"; g; "*/"


It should output, with other parameters "g" and "a", this:

var a = 1; "g\"g"; "g'"; a; '"g\'g"g'; /g"\/*\//g; a; "// /*"; a; "*/"


(sidenote: I really like /g"\/*\//g; I think that's just evil :D)



Full specification:


For simplicity, you may ignore scope. Ex. "var a=1; function(){var a=2;}; var o={a: 3}", "a", "b" can output var b=1; function(){var b=2;}; var o={b: 3}.
Text in strings ('...' and "..."), regexps and their modifiers (/.../...), and comments (//...\n and /*...*/) must not be modified.
Also for simplicity, a valid identifier is one that starts with a letter, dollar sign, or underscore, and the rest of the characters are letters, numbers, dollar signs, or underscores.
You may assume that the input contains no syntax errors.
This is code-golf, so the shortest code in bytes will win.
If you use network access, all bytes downloaded from the network count towards your score.
You must use an actual programming language. No IDE solutions, like emacs or vim keystrokes. ;)
Ruby, 134 (113?) characters
*c,o,n=*$&lt;;puts (c*?\n).gsub(/('|&quot;)((\\?+.)*?)\1|\/\*[\s\S]*?\*\/|\/\/.*|\/(\[\g&lt;2&gt;\]|\g&lt;2&gt;)+?\/\w*|([\w$]+)/){$5==o.chop&amp;&amp;n.chop||$&amp;}

Unicode is not supported. If Unicode identifiers are to be supported, replace \w with [[:word:]]  and [\w$] with ([[:word:]]|\$) (and adjust the backreferences).
If unescaped slashes inside regexp literals (such as /[/]/) don't need to be supported, we can handle them together with string literals (116 characters). This also gives us string flags:
*c,o,n=*$&lt;;puts (c*?\n).gsub(/\/\*[\s\S]*?\*\/|\/\/.*|('|&quot;|\/)((\\?+.)*?)\1\w*|([\w$]+)/){$4==o.chop&amp;&amp;n.chop||$&amp;}

Ungolfed version:
*code, old, new = *$&lt;

puts code.join(&quot;\n&quot;).gsub (/
     ('|&quot;)((\\?+.)*?)\1           #strings
   | \/\*[\s\S]*?\*\/             #multiline comments
   | \/\/.*                       #single-line comments
   | \/(\[\g&lt;2&gt;\]|\g&lt;2&gt;)+?\/\w*   #regexes
   | ([\w$]+)                     #identifiers and keywords
/x){
  if $5 == old.chop then new.chop else $&amp; end
}