4

In a string, I need to replace all occurences of [A], "A", 'A' and _A_ with [X], "X", 'X' and _X_. I tried this answer but it's giving a weird result (code below). I use new RegExp because it allows interpolating a variable -- A and X are just an example.

// CAPTURE GROUPS:       |------1-----|2|-----3------|
var regexp = new RegExp('(\'|\"|\_|\[)(A)(\'|\"|\_|\])', 'g')
var string = ' [A] _A_ "A" \'A\' A BAB "B" '
string.replace(regex, '$1X$3')

// ORIGINAL: [A] _A_ "A" 'A' A BAB "B" 
// EXPECTED: [X] _X_ "X" 'X' A BAB "B"
// ACTUAL:   [X] XXX XXX XXX X BXB XBX
Community
  • 1
  • 1
João Souza
  • 4,032
  • 3
  • 25
  • 38
  • 2
    When you build a regular expression from a string like that, the backslash escape characters must be **doubled**. – Pointy May 14 '17 at 14:36
  • To prevent what pointy pointed (\*g\*) out, use the Regex literal syntax instead of the constructor. – Christoph May 14 '17 at 14:40
  • @Pointy doubling the backslash **only before the square brackets** works! -- but doubling the others gives syntax error, just for the record. – João Souza May 14 '17 at 18:05
  • @Christoph I don't think it's possible to interpolate a variable in a regex literal. As I said, 2 and X are just examples. The actual value is in a variable so I need the constructor. – João Souza May 14 '17 at 18:11

1 Answers1

6

The problem is caused by the two layers of interpretation that the backslashes undergo. First you have JavaScript's string literal syntax, which uses backslashes to escape characters. When you have a string like

'(\'|\"|\_|\[)(A)(\'|\"|\_|\])'

in your code, the actual contents are:

('|"|_|[)(A)('|"|_|])

This is then parsed by the RegExp constructor, which treats [)(A)('|"|_|] as a single character class equivalent to [A'"_()|].

To preserve a backslash so the regexp engine can see it, you have to put two backslashes in your string.

You can also use character classes to simplify your code a bit:

var regex = new RegExp('([\'"_[])A([\'"_\\]])', 'g')
var string = ' [A] _A_ "A" \'A\' A BAB "B" '
console.log(string.replace(regex, '$1X$2'));
melpomene
  • 84,125
  • 8
  • 85
  • 148