Skip to content

Instantly share code, notes, and snippets.

@getify
Last active July 11, 2019 23:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save getify/f9df482f89ac8cdc17f339c81da74c3d to your computer and use it in GitHub Desktop.
Save getify/f9df482f89ac8cdc17f339c81da74c3d to your computer and use it in GitHub Desktop.
what could a `replaceAll(..)` for JS strings, which handles non-global regexes as if they're global, look like?
function replaceAll(str,re,replacement) {
if (re.global) {
return str.replace(re,replacement);
}
else {
// do we need to "patch" the replacement function to pass correct arguments?
if (typeof replacement == "function") {
let fn = replacement;
replacement = function replacer(...args) {
// patch `offset` to correct position from whole string
args[args.length - 2] += processed.length;
// patch "whole string"
args[args.length - 1] = str;
return fn(...args);
};
}
let match;
let processed = "";
let stillToProcess = str;
do {
// preserve lastIndex in case this is a /y sticky regex
let reLastIdx = re.lastIndex;
// check to see if there's any replacement to be made?
// NOTE: for a /y sticky regex, `lastIndex` WILL BE changed
match = stillToProcess.match(re);
if (match) {
// restore lastIndex in case this is a /y sticky regex
re.lastIndex = reLastIdx;
// perform the replacement
let s = stillToProcess.replace(re,replacement);
// where would the virtual `lastIndex`` be if this were a global regex?
let lastIndex = match.index + match[0].length;
// move newly-replaced chunk into processed accumulator
processed += s.slice(0,lastIndex);
// remove newly-replaced chunk from what's left still to process
stillToProcess = s.slice(lastIndex);
// fix `lastIndex` if it's a /y sticky regex
if (re.sticky) {
re.lastIndex = 0;
}
}
}
while (match);
// anything left at the end of the string?
if (stillToProcess.length > 0) {
processed += stillToProcess;
}
return processed;
}
}
replaceAll("Hello World",/l/,"L"); // "HeLLo WorLd"
replaceAll("Hello World",/l/,x => x.toUpperCase()); // "HeLLo WorLd"
replaceAll("abcabc",/ab/,"ab"); // "abcabc"
replaceAll("abcabc",/./,"X"); // "XXXXXX"
replaceAll("ababab",/ab/,"AB"); // "ABABAB"
replaceAll("ababab",/ab/y,"AB"); // "ABABAB"
replaceAll("abcabc",/ab/y,"AB"); // "ABcabc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment