0

I have a script that is more or less used like this:

var $pencilers = {
    '\\(signed\\)': '(assinado)',
    'pencils': 'arte',
    '\\[as ': '[como '
};

var $pencils = 'Al Williamson [as A. W.] (signed)'
var pen = new RegExp(Object.keys($pencilers).join("|"),"g");
$pencils = $pencils.replace(pen, function(matched){
      return $pencilers[matched];
});

console.log($pencils)

// $pencils returns: Al Williamson undefinedA. W.] undefined

Can't figure out why does it returns undefined.

When I test it in Regex101 it works perfectly. Can anyone help out?

Emma
  • 27,428
  • 11
  • 44
  • 69
jaclerigo
  • 557
  • 2
  • 6
  • 31

1 Answers1

3

If you did a console.log(matched), you'd notice that your matches don't match the object keys. You have to escape the strings first. I borrowed this neat escape function to make it work:

function escapeRegExp(string) {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}

var $pencilers = {
    '\\(signed\\)': '(assinado)',
    'pencils': 'arte',
    '\\[as ': '[como '
};

var $pencils = $("#id_pencils").val(); // eg. Al Williamson [as A. W.] (signed) //
var pen = new RegExp(Object.keys($pencilers).join("|"),"g");
$pencils = $pencils.replace(pen, function(matched){
      console.log('before escaping: ', matched);
      matched = escapeRegExp(matched);
      console.log('after escaping: ', matched);
      return $pencilers[matched];
});
console.log($pencils);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="id_pencils" value="Al Williamson [as A. W.] (signed)" />

You could also turn it around and leave your object keys unescaped, escaping them when building your regex. In fact, I'd prefer and recommend to use this approach, as it makes your code more readable.

function escapeRegExp(string) {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}

var $pencilers = {
    '(signed)': '(assinado)',
    'pencils': 'arte',
    '[as ': '[como '
};

var $pencils = $("#id_pencils").val(); // eg. Al Williamson [as A. W.] (signed) //
var pen = new RegExp(Object.keys($pencilers).map(escapeRegExp).join("|"),"g");
$pencils = $pencils.replace(pen, function(matched){
      return $pencilers[matched];
});
console.log($pencils);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="id_pencils" value="Al Williamson [as A. W.] (signed)" />
Constantin Groß
  • 10,719
  • 4
  • 24
  • 50