user8210822
user8210822

Reputation:

Replace double backslash with single backslash in JavaScript

I am writing a function that will remove a \\ and replace it with a \. I notice that the code also does not work for backslashes that aren't powers of two (other than two, of course).

function x(input){
  var arr = [];
  for(var i = 0; i < input.length; i++){
    var result = input[i].replace(/\\\\/g, '\\');
    arr.push(result);
  }

  return arr;
}

console.log(x(['\\a']));

The code will return [ '\\a' ].

EDIT:

Here is a more complicated example:

Input : ["\\\\\\"\\"a\\""] Output : [ '\\""a"' ] Desired output: ["\\\"\"a\""]

Upvotes: 1

Views: 5408

Answers (2)

zer00ne
zer00ne

Reputation: 44088

When using regex,

  • a literal reverse solidus (a.k.a. backslash,( a.k.a. \)) must be escaped with a \ .

  • So when you input \\, that's literally \.

  • If you want to input 2 \ each one must be escaped. That means \\\\ is literally a string of 2 \.

The following demo uses ES6 Template Literals:

  • It's a new syntax for String that uses the backtick ` (top left corner key) instead of quotes " or '.

  • It can interpolate variables by prefixing with ${ and suffixing with }.

    var x = 2; `this template literal will display x as ${x}.`
    // this template literal will display x as 2.
    
  • The \ is U+5c in unicode. Using escaped unicode in Template Literal, it would be prefixed with \u{ and suffixed with }

    `A template literal with an escaped unicode backslash is \u{5c}`
    // A template literal with an escaped unicode backslash is \.
    

Demo

function XtoY(str, x, y) {
  var rgx = `/${x}/g`;
  var result = str.replace(rgx, `${y}`);
  return result;
}

const uni = `\u{5c}`;
const string = `\\a\\a\\b`;
const from = `${uni}${uni}`
const to = `${uni}`;

let z = XtoY(string, from, to);

console.log(z);

Upvotes: 3

ABabin
ABabin

Reputation: 2947

When we pass in "["\\\\\\"\\"a\\""]" into with console.log(), the string that the function actually sees looks like "["\\\"\"a\""]" because the input string is being escaped before being passed to the function. The replace regex looks for double backslashes, so given the input, it will only match the first two backslashes of that group of three, replacing it with one, and leaving the rest as is... which is why it will return "["\\"\"a\""]".

If you call the function, getting the input string from an input field, for instance, your function works as desired.

If you WANT to achieve your desired result using explicit string literals, you can use /\\/g as the replace regex (effectively just not doing the replace at all), but it will not work both ways unless, as far as I know, you provide the function a way of knowing where the string came from (perhaps with an optional parameter) and manually handling the possibilities.

For example:

function x(input, caller) {
  return input.replace(caller === 'console' ? /\\/g : /\\\\/g, "\\");
}

console.log(x('["\\\\\\\"\\"a\\""]', "console"));

$("button").click(function() {
  console.log(x($("input").val()));
});

That checks if the call to the x function was passed a 2nd parameter with the value of "console" and changes the regex for the replace function accordingly.

Upvotes: 0

Related Questions