3

I want to split a string in 2 parts separated by '|', but not separated if '|' before is '\'.

Input

example_str = 'a|b\\|c'

Output

st1 ='a'
st2 ='b|c'
sean su
  • 41
  • 4

5 Answers5

3

These kinds of task can be solved by state machine approach. Simply saying, in your case: you need to build cycle for each character. When we see \ we move current state to ESCAPE and on next interaction when we are in ESCAPE state we need to reset state to normal state. If we see | and we are not in ESCAPE state we need to copy this part of text and push it to array.

You should also decide, what should be the result for a|b\\|c.

Alex Kapustin
  • 1,869
  • 12
  • 15
1

You can replace the \| with a unique string, then split on the pipe, then replace the unique string back to \|

Like this, https://jsfiddle.net/gb3Ljugc/

const aUniqueStringNotFoundInData = '___UNIQUE_____';
let x = 'a|b\\|c'.replace('\\\|', aUniqueStringNotFoundInData).split('\|');
x = x.reduce((acc, val) => {
    val = val.replace(aUniqueStringNotFoundInData, '\\\|');
  return acc.concat(val);
},[])
console.log(x);
sissonb
  • 3,730
  • 4
  • 27
  • 54
1
var test = "a|b\\|c";
test = test.replace('\\|','%%');
var testArray = test.split('|')


for(x = 0; x < testArray.length; x++)
{
    testArray[x] = testArray[x].replace('%%', '\\|');
}

var st1 = testArray[0];
var st2 = testArray[1];
Harry
  • 3,930
  • 2
  • 14
  • 31
0

I believe that there is no way to achieve what you're asking about because in JS string literals 'a|b\|c' and 'a|b|c' are equivalent. Check this please:

var s1 = 'a|b\|c';
var s2 = 'a|b|c';
console.log(s1 === s2);

Still if input string is correctly escaped you may try combine split with reduce. Sorry for ES6 spread operator

var s = 'a|b\\|c';
var arr =  s.split('|')
var result = arr.reduce((acc, item) => {
    if (acc.length && acc[acc.length - 1] && acc[acc.length - 1].endsWith('\\')) {
        acc[acc.length - 1] = acc[acc.length - 1].substring(0, acc.length - 1) + '|' + item;
        return acc;
    }
    return [...acc, item];
}
, []);
-1

You lose the first pipe anyhow, so replace it with something else and then split by that:

const [str1, str2] = 'a|b\|c'.replace('|', ' ').split(' ');
Mark
  • 521
  • 6
  • 15
  • That doesn't work at all. Not only does it fail to consider backslashes (which is the whole point of the question!), but it'll also break if the original string includes spaces. –  Nov 10 '17 at 23:34
  • Strictly speaking it does work for this very specific case, just not the implied general problem. – Rob Hogan Nov 10 '17 at 23:36
  • 2
    @RobHogan so does `return ['a', 'b\|c'];` – Blorgbeard Nov 10 '17 at 23:37
  • Quite right! But there’s something to be said for being literally correct, especially in an unnecesssarily obscure way. The question didn’t ask for a general solution ;) – Rob Hogan Nov 10 '17 at 23:49
  • And you think he doesn't want a general solution—just this this very specific case? That's your honest take on it? – ErikE Nov 11 '17 at 00:55
  • Me? No, I assumed a generalised answer was desired. Look at this answer though, the destructuring and logic - it's not an incorrect attempt at the general problem, it's an apparently well-intentioned, unassuming answer to the literal question. I found it interesting/amusing that we'd all made an assumption this answer doesn't. I probably have a strange sense of humour though - forget it! – Rob Hogan Nov 11 '17 at 01:32