简体   繁体   中英

Multiple replace with special characters

I am trying to refactor some code:

const newValue = value
  .replace(/\{1\}/g, '<i class="ms ms-1 inline"></i>')
  .replace(/\{2\}/g, '<i class="ms ms-2 inline"></i>')
  ... etc etc
return newValue;

I would prefer not to use replace each time.


I have been trying the following without success:

const mapObj = {
  '/\{1\}/': '<i class="ms ms-1 inline"></i>',
  '/\{2\}/': '<i class="ms ms-2 inline"></i>',
  ...
}
const reg = new RegExp(Object.keys(mapObj).join("|"), "g");
return value.replace(reg, (m) => mapObj[m]);

For simple replaces this usually works pretty well, however because of the need to escape the special characters ( { and } ) something is clearly going wrong with my regex pattern in the mapObj object.

Here is demo of the current simplified code .

How do I go about fixing the pattern ( /\\{1\\}/ ) in the mapObj to get the refactored code to work?

If your replacments really are the same other than ms-1 for {1} and ms-2 for {2} , then use a capture group:

return value.replace(/\{(\d)}/g, '<i class="ms ms-$1 inline"></i>');

The $1 is the content of the capture group. That expression matches a single digit within {} ; adjust as needed.

Live Example:

 function process(value) { return value.replace(/\\{(\\d)}/g, '<i class="ms ms-$1 inline"></i>'); } console.log(process("Testing {1} testing {2}")); 


If the replacements vary and you really need to map them, use the function callback:

const mapObj = {
    "{1}": "replacement for 1",
    "{2}": "different replacement for 2"
};
return value.replace(/\{\d}/g, m => mapObj[m] || "some default");

You could use a capture group to avoid having to repeat {} in the keys in mapObj .

Live Example:

 const mapObj = { "{1}": "replacement for 1", "{2}": "different replacement for 2" }; function process(value) { return value.replace(/\\{\\d}/g, m => mapObj[m] || "some default"); } console.log(process("Testing {1} testing {2}")); 

It appears that your refactor is confusing string, regular expressions, and the escape sequences for both.

Given your code...

const mapObj = {
  '/\{1\}/': '<i class="ms ms-1 inline"></i>',
  '/\{2\}/': '<i class="ms ms-2 inline"></i>',
  ...
}
const reg = new RegExp(Object.keys(mapObj).join("|"), "g");
return value.replace(reg, (m) => mapObj[m]);
  1. The reg regular expression will be /\\/{1}\\/|\\/{2}\\//g , (which is looking for curly brackets surrounded by slashes,) which is not what you want. You want something like /\\{1\\}|\\{2\\}/g

  2. The (m) => mapObj[m] won't work as intended, because the value string will have words like "pay {1} to cast" , whereas mapObj[m] is looking for keys like "\\/{1}\\/" (note the slashes around the curly brackets)

What you want to do is remove the unnecessary / slashes when converting between Regex and strings and back.

Recommended solution:

function magicReplace(value) {
  mapObj = {
    '{1}': '<i class="ms ms-1 inline"></i>',
    '{2}': '<i class="ms ms-2 inline"></i>',
  };
  reg = new RegExp( Object.keys(mapObj).join("|").replace(/\{/g, '\\{').replace(/\}/g, '\\}'), "g");
  return value.replace(reg, (m) => mapObj[m]);
}

magicReplace('Whenever you cast a spell, you may pay {1}.');
//Returns: 'Whenever you cast a spell, you may pay <i class="ms ms-1 inline"></i>.'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM