12

I have this string:

a\,bcde,fgh,ijk\,lmno,pqrst\,uv

I need a JavaScript function that will split the string by every , but only those that don't have a \ before them

How can this be done?

pimvdb
  • 151,816
  • 78
  • 307
  • 352
Ovi
  • 2,459
  • 9
  • 50
  • 72
  • Duplicate question? http://stackoverflow.com/questions/820172/how-to-split-a-comma-separated-string-while-ignoring-escaped-commas – Eran Medan Sep 07 '11 at 07:01
  • 1
    @Eran that question is about Java. Unfortunately Javascript does not know lookbehinds, so that solution is not working here. – stema Sep 07 '11 at 07:05
  • possible duplicate of [Javascript regex - split string](http://stackoverflow.com/questions/4853118/javascript-regex-split-string) – outis Feb 19 '12 at 18:57

6 Answers6

12

Here's the shortest thing I could come up with:

'a\\,bcde,fgh,ijk\\,lmno,pqrst\\,uv'.replace(/([^\\]),/g, '$1\u000B').split('\u000B')

The idea behind is to find every place where comma isn't prefixed with a backslash, replace those with string that is uncommon to come up in your strings and then split by that uncommon string.

Note that backslashes before commas have to be escaped using another backslash. Otherwise, javascript treats form \, as escaped comma and produce simply a comma out of it! In other words if you won't escape the backslash, javascript sees this: a\,bcde,fgh,ijk\,lmno,pqrst\,uv as this a,bcde,fgh,ijk,lmno,pqrst,uv.

Community
  • 1
  • 1
WTK
  • 16,583
  • 6
  • 35
  • 45
  • Thanks, why are you using a `~`? – Ovi Sep 07 '11 at 07:20
  • You can use anything instead of `~`. It have to be something (even something longer than `~`) that you are sure won't come up in a string that is being split up, because in the next step (after replace) we're splitting the string using that character(s). – WTK Sep 07 '11 at 07:22
  • I recommend using any non-printable character instead of ~. E.g. it can be \u000B which corresponds to code of zero-width space. – Eskat0n Sep 07 '11 at 07:22
  • What didn't do anything? :) Please note, that backslashes before colons **has to be escaped** using another backslash. Otherwise, javascript treats form `\,` as escaped colon and produce simply colon out of it! In other words if you won't escape the backslash, javascript sees this: `a\,bcde,fgh,ijk\,lmno,pqrst\,uv` as this `a,bcde,fgh,ijk,lmno,pqrst,uv`. – WTK Sep 07 '11 at 07:30
4

Since regular expressions in JavaScript does not support lookbehinds, I'm not going to cook up a giant hack to mimic this behavior. Instead, you can just split() on all commas (,) and then glue back the pieces that shouldn't have been split in the first place.

Quick 'n' dirty demo:

var str = 'a\\,bcde,fgh,ijk\\,lmno,pqrst\\,uv'.split(','), // Split on all commas
    out = []; // Output

for (var i = 0, j = str.length - 1; i < j; i++) { // Iterate all but last (last can never be glued to non-existing next)
    var curr = str[i]; // This piece
    if (curr.charAt(curr.length - 1) == '\\') { // If ends with \ ...
        curr += ',' + str[++i]; // ... glue with next and skip next (increment i)
    }
    out.push(curr); // Add to output
}
jensgram
  • 31,109
  • 6
  • 81
  • 98
  • I think this solution look like a very big workaround while there is solution presented by WTK – Eskat0n Sep 07 '11 at 07:25
  • @Eskat0n Indeed it *is* a workaround ... a workaround that happens to span more lines than other answers :) – jensgram Sep 07 '11 at 07:40
  • This solution fails if you have multiple escaped ',' before a non escaped ','. E.G. `"ab\\,c\\,ed,fg"`. Change: `for (var i = 0, j = str.length - 1; i < j; i++) {` to: `while (var i = 0, j = str.length - 1; i < j; i++) {` to fix this issue. – DLKJ Sep 09 '13 at 11:36
1

Another ugly hack around the lack of look-behinds:

function rev(s) {
    return s.split('').reverse().join('');
}

var s = 'a\\,bcde,fgh,ijk\\,lmno,pqrst\\,uv';

// Enter bizarro world...
var r = rev(s);

// Split with a look-ahead
var rparts = r.split(/,(?!\\)/);

// And put it back together with double reversing.
var sparts = [ ];
while(rparts.length)
    sparts.push(rev(rparts.pop()));

for(var i = 0; i < sparts.length; ++i)
    $('#out').append('<pre>' + sparts[i] + '</pre>');

Demo: http://jsfiddle.net/ambiguous/QbBfw/1/

I don't think I'd do this in real life but it works even if it does make me feel dirty. Consider this a curiosity rather than something you should really use.

mu is too short
  • 426,620
  • 70
  • 833
  • 800
0

In case if need remove backslashes also:

var test='a\\.b.c';
var result = test.replace(/\\?\./g, function (t) { return t == '.' ? '\u000B' : '.'; }).split('\u000B');
//result: ["a.b", "c"]
Gene R
  • 3,684
  • 2
  • 17
  • 27
0

In 2022 most of browsers support lookbehinds: https://caniuse.com/js-regexp-lookbehind

Safari should be your only concern.

With a lookbehind you can split your string this way:

"a\\,bcde,fgh,ijk\\,lmno,pqrst\\,uv".split(/(?<!\\),/)
// => ['a\\,bcde', 'fgh', 'ijk\\,lmno', 'pqrst\\,uv']
gtournie
  • 4,143
  • 1
  • 21
  • 22
-1

You can use regex to do the split.

Here is the link to regex in javascript http://www.w3schools.com/jsref/jsref_obj_regexp.asp

Here is the link to other post where the author have used regex for split Javascript won't split using regex

From the first link if you note you can create a regular expression using

?!n Matches any string that is not followed by a specific string n

[,]!\\
Community
  • 1
  • 1
Rahul Choudhary
  • 3,789
  • 2
  • 30
  • 30
  • 2
    Of course you can use a regex to split the string. Question is HOW to split the string in a way author asked for. – WTK Sep 07 '11 at 07:05
  • Yeah, this is not what the author wants. I'm thinking to loop with .each every split with commas, and check wheter the previous each part has or not a "/" at the end... If it has, concat both – GoRoS Sep 07 '11 at 07:08
  • @WTK The first link covered the answer, just didn't wanted spoonfeeding. Have edited the answer again to include more information based on your suggestions though – Rahul Choudhary Sep 07 '11 at 07:12
  • @ GoRoS, can you please write the exact function for you idea? – Ovi Sep 07 '11 at 07:17
  • Yeah, I'd like to see that too. Note that link provided in the first comment was refering to Java which has different implementation of regular expression. – WTK Sep 07 '11 at 07:28