WastedSpace
WastedSpace

Reputation: 1143

Javascript regex - split string

Struggling with a regex requirement. I need to split a string into an array wherever it finds a forward slash. But not if the forward slash is preceded by an escape.

Eg, if I have this string:

hello/world

I would like it to be split into an array like so:

arrayName[0] = hello
arrayName[1] = world

And if I have this string:

hello/wo\/rld

I would like it to be split into an array like so:

arrayName[0] = hello
arrayName[1] = wo/rld

Any ideas?

Upvotes: 15

Views: 27780

Answers (7)

Alan Moore
Alan Moore

Reputation: 75272

I wouldn't use split() for this job. It's much easier to match the path components themselves, rather than the delimiters. For example:

var subject = 'hello/wo\\/rld';
var regex = /(?:[^\/\\]+|\\.)+/g;
var matched = null;
while (matched = regex.exec(subject)) {
  print(matched[0]);
}

output:

hello
wo\/rld

test it at ideone.com

Upvotes: 23

kennebec
kennebec

Reputation: 104850

/* If you are getting your string from an ajax response or a data base query, that is, the string has not been interpreted by javascript, you can match character sequences that either have no slash or have escaped slashes. If you are defining the string in a script, escape the escapes and strip them after the match. */

var s='hello/wor\\/ld';
s=s.match(/(([^\/]*(\\\/)+)([^\/]*)+|([^\/]+))/g) || [s];
alert(s.join('\n'))
s.join('\n').replace(/\\/g,'')

/*  returned value: (String)
hello
wor/ld
*/

Upvotes: 1

Tim Down
Tim Down

Reputation: 324727

The following is a little long-winded but will work, and avoids the problem with IE's broken split implementation by not using a regular expression.

function splitPath(str) {
    var rawParts = str.split("/"), parts = [];
    for (var i = 0, len = rawParts.length, part; i < len; ++i) {
        part = "";
        while (rawParts[i].slice(-1) == "\\") {
            part += rawParts[i++].slice(0, -1) + "/";
        }
        parts.push(part + rawParts[i]);
    }
    return parts;
}

var str = "hello/world\\/foo/bar";
alert( splitPath(str).join(",") );

Upvotes: 3

Hemlock
Hemlock

Reputation: 6208

Something like this may take care of it for you.

var str = "/hello/wo\\/rld/";
var split = str.replace(/^\/|\\?\/|\/$/g, function(match) {
  if (match.indexOf('\\') == -1) {
    return '\x00';
  }
  return match;
}).split('\x00');       

alert(split);

Upvotes: 0

Mike Samuel
Mike Samuel

Reputation: 120586

For short code, you can use reverse to simulate negative lookbehind

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

var parts = reverse(myString).split(/[/](?!\\(?:\\\\)*(?:[^\\]|$))/g).reverse();
for (var i = parts.length; --i >= 0;) { parts[i] = reverse(parts[i]); }

but to be efficient, it's probably better to split on /[/]/ and then walk the array and rejoin elements that have an escape at the end.

Upvotes: 0

T.J. Crowder
T.J. Crowder

Reputation: 1075875

Here's a way adapted from the techniques in this blog post:

var str = "Testing/one\\/two\\/three";
var result = str.replace(/(\\)?\//g, function($0, $1){
  return $1 ? '/' : '[****]';
}).split('[****]');

Live example

Given:

Testing/one\/two\/three

The result is:

[0]: Testing
[1]: one/two/three

That first uses the simple "fake" lookbehind to replace / with [****] and to replace \/ with /, then splits on the [****] value. (Obviously, replace [****] with anything that won't be in the string.)

Upvotes: 3

Mikhail
Mikhail

Reputation: 9007

Here's an example at rubular.com

Upvotes: 0

Related Questions