javascript - string replacement, replace "^" with "" and "^^" with "^"

Viewed 147

Removing Temporary Escape Characters in JavaScript...

Basic Example:

I have the following string:

"[x^::^^y]"

And the output should be:

"[x::^y]"

Essentially, any occurrences of ^ that do not neighbor another ^ should be removed, and any occurences of ^^ should be replaced with ^

More Examples:

.parse("[^^x:^y^:^^^^^^]") // output: "[^x:y:^^^]"
.parse("[^x:^^^^y^^^z]") // output: "[x:^^y^z]"

It will be part of the parsing script for a JSON alternative that I'm developing to hopefully reduce file sizes for internal storage files.

4 Answers

I would use .replace() with a replacer function like this:

function parse (str) {
  return str.replace(/\^{1,2}/g, s => s.slice(1));
}

console.log(parse('[x^::^^y]'));
console.log(parse('[^^x:^y^:^^^^^^]'));
console.log(parse('[^x:^^^^y^^^z]'));

One more idea: Capture one ^ of pairs to $1 or don't capture the remaining and replace with $1.

function parse (s) {
  return s.replace(/(\^)\^|\^/g, '$1');
}

console.log(parse('[^x:^^^^y^^^z]'));

@PatrickRoberts comment: The pattern can be further reduced to: \^(\^?)

Since a replace call will work on entire string, the two replaces, if executed one after another, will interfere with each other. Regardless of the order in which replaces are called this will always end up in wrong result.

The only way to solve this would be to use an intermediate state. For example if we were to use + as intermediate symbol it'd be something like:

  1. Replace ^^ with +,
  2. Fllowed by replace ^ with empty string,
  3. Then, replace + with ^

Obviously + symbol might appear in the original string itself, so you'd need to select a better intermediate symbol which wouldn't appear in original string. It can very well be multi character or even a control character.

EDIT: The accepted answer to use the replacer function is much better approach for JS. I am leaving this answer here just in case someone stumbles upon this question with similar problem in some other language where replacer functions are not available.

Excellent answers above !!

But another way it may be done is to use lookahead and lookbehind.

function replace_carets(mystring) {
  return mystring
    .replace(/(?<!\^)(\^{2})*\^(?!\^)/g, "$1") //removes isolated ^ or last odd numbered ^
    .replace(/\^{2}/g, "^"); //replaces ^^ with ^
}
console.log(replace_carets("[x^::^^y]"));
console.log(replace_carets("[^^x:^y^:^^^^^^]"));
console.log(replace_carets("[^x:^^^^y^^^z]"));

Far from elegant but I challenged myself to do it alternatively so sharing with you.

Related