AgentM AgentM - 3 months ago 19
Javascript Question

Regexp nothing to repeat using a variable inside a replace function

JS:

oldString = "I really love this font for some reason!";

var oldF = 0;
var newF = 1;

fonts = ["abcdefghijklmnopqrstuvwxyz0123456789 !@#$%^&*()_+-=[]{};'\\:\"|,./<>?","abcdefghijklmnopqrstuvwxyz0123456789 !@#$%^&*()_+-=[]{};'\:"|,./<>?","ᴀʙᴄᴅᴇғɢʜɪᴊᴋʟᴍɴᴏᴘǫʀsᴛᴜᴠᴡxʏᴢ⁰¹²³⁴⁵⁶⁷⁸⁹ ","ⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ⓪①②③④⑤⑥⑦⑧⑨ ","ɐqɔpǝɟƃɥıɾʞlɯuodbɹsʇnʌʍxʎz0ƖᄅƐㄣϛ9ㄥ86 "];

newString = oldString;

for (i = 0; i < fonts[oldF].length; i++) {
var re = new RegExp(fonts[oldF][i], "gi");
newString = newString.replace(re, fonts[newF][i]);
}

if (newF == 4 ^ oldF == 4) {
var o = '';
for (var i = newString.length - 1; i >= 0; i--) {
o += newString[i];
}
newString = o;
}

newString;


now at line 17 (var re = new ...) it gives an "nothing to repeat" error, the problem is that I use 'i' to select a character from the string (char array) 'fonts' which means if I use escape characters, it will choose the '\' but I actually want ( to be taken in entirely, I don't know of a better way than to put these special cases in a separate function or to detect an escape character and handle that differently.

Answer

You need to escape the regex special characters (-,[,],/,{,},(,),*,+,?,.,\,^,$,|).

function escapeRegExp(str) {
  return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
}

oldString = "I really love this font for some reason!";

var oldF = 0;
var newF = 1;

fonts = ["abcdefghijklmnopqrstuvwxyz0123456789 !@#$%^&*()_+-=[]{};'\\:\"|,./<>?","abcdefghijklmnopqrstuvwxyz0123456789 !@#$%^&*()_+-=[]{};'\:"|,./<>?","ᴀʙᴄᴅᴇғɢʜɪᴊᴋʟᴍɴᴏᴘǫʀsᴛᴜᴠᴡxʏᴢ⁰¹²³⁴⁵⁶⁷⁸⁹ ","ⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ⓪①②③④⑤⑥⑦⑧⑨ ","ɐqɔpǝɟƃɥıɾʞlɯuodbɹsʇnʌʍxʎz0ƖᄅƐㄣϛ9ㄥ86 "];

newString = oldString;

for (i = 0; i < fonts[oldF].length; i++) {
    var re = new RegExp(escapeRegExp(fonts[oldF][i]), "gi");
    newString = newString.replace(re, fonts[newF][i]);
}

if (newF == 4 ^ oldF == 4) {
    var o = '';
    for (var i = newString.length - 1; i >= 0; i--) {
        o += newString[i];
    }
    newString = o;
}

console.log(newString);

escapeRegExp function copied from: Escape string for use in Javascript regex

Update:

What you are trying to do is really inefficient and harder than if you just used did some string character mapping. Check out the below updated code.

function escapeRegExp(str) {
  return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
}

oldString = "I really love this font for some reason!";

var oldF = 0;
var newF = 4;

fonts = ["abcdefghijklmnopqrstuvwxyz0123456789 !@#$%^&*()_+-=[]{};'\\:\"|,./<>?","abcdefghijklmnopqrstuvwxyz0123456789 !@#$%^&*()_+-=[]{};'\:"|,./<>?","ᴀʙᴄᴅᴇғɢʜɪᴊᴋʟᴍɴᴏᴘǫʀsᴛᴜᴠᴡxʏᴢ⁰¹²³⁴⁵⁶⁷⁸⁹ ","ⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ⓪①②③④⑤⑥⑦⑧⑨ ","ɐqɔpǝɟƃɥıɾʞlɯuodbɹsʇnʌʍxʎz0ƖᄅƐㄣϛ9ㄥ86 "];

newString = oldString;
newString1 = newString;

var t0 = performance.now();
for (i = 0; i < fonts[oldF].length; i++) {
    var re = new RegExp(escapeRegExp(fonts[oldF][i]), "gi");
    newString = newString.replace(re, fonts[newF][i]);
}
var t1 = performance.now();
console.log("Regex Time: "+(t1-t0));

t0 = performance.now();
newString1 = newString1.split("").map(c => fonts[newF][fonts[oldF].indexOf(c.toLowerCase())]).join("");
t1 = performance.now();
console.log("Map Time: "+(t1-t0));


console.log("Regex Output: "+newString);
console.log("Map Output: "+newString1);

Comments