15

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?

1
  • This page will probably help: blog.stevenlevithan.com/archives/mimic-lookbehind-javascript Not posting this as an answer because I don't have time right now to come up with an example specific to what you need. But I'm quite certain you can get there from that post. Good luck. Commented Jan 31, 2011 at 16:15

7 Answers 7

23

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

Sign up to request clarification or add additional context in comments.

2 Comments

This looks the best answer to me.
Agreed. Definitely the best answer.
3

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(",") );

1 Comment

Cheers! This seems like the solution I've been looking for.
3

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.)

1 Comment

Thanks :) This is the kind of thing that would be suitable for me.
1

/* 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
*/

Comments

0

Here's an example at rubular.com

6 Comments

Which may be great for Ruby, but doesn't look like it works for JavaScript, at least not with split: jsbin.com/ipote5 If you were thinking of using it another way, I'd recommend posting that.
Please post the solution here instead of on another site.
This doesn't work: "hello/wor\/rld".match(/([a-z]+(\\\/)?[a-z]+)/) => ["hello", "hello", undefined]
@Justin: It does work if you use the g identifier str.match(/[a-z]+(\\\/)?[a-z]+/g);, but it fails if there's more than one \/. (Or any other characters beside lowercase letters for that matter)
Hence the importance of posting the solution here as you said.
|
0

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.

Comments

0

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);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.