babo221
babo221

Reputation: 63

How to make a regex for capturing one symbol only, but with restrictions?

I need a regex for javascript that allows me to select a single character with a restriction: that it does NOT have a specified character besides itself.

I need to select the character / but only if it does NOT have the character a besides it.

E.g.:

str = "I Like this/ and a/ basketball is round a/a ups.Papa/ tol/d /me tha/t";

myregex = ????
var patt = new RegExp(myregex);
var res = patt.split(str);

And the result should be something like this:

res[0] = "I Like this"
res[1] = " and a/ basketball is round a/a ups.Papa/ tol"
res[2] = "d "
res[3] = "me tha/t"

The regex should be something like: (if a then not)(\/)(if a then not)

I have no idea how to do it, I tried: [^a](\/)[^a], but then it selects also the characters that are beside the /, like s/, l/d, not the a's; I don't want to select the characters beside the /.

Upvotes: 6

Views: 90

Answers (2)

Soul Reaver
Soul Reaver

Reputation: 2092

For now it seems not possible to do it with regex in JavaScript as lookbehind is not implemented in all browsers. Partial solution would be /\/(?!a)/g, this will match any / which is not followed by a. Full solution, with lookbehind, if this will get someday implemented in all major browser engines, would need the part from gurvinder372's answer, which gives us: /(?<!a)\/(?!a)/g


EDIT: It seems, like this should be soon available in other browsers as well. TC39, responsible for ECMAScript specification, pushed proposal for insertion of RegEx lookbehind to stage 4 - finished on 24th (with some changes on 26th) of January. Here you can find some information about it and here you can check current browser support. At the moment of writing, only Chrome/Opera tandem (same engine) supports lookbehind.

As for "when" will be this "soon" - I don't know much about Safari and iOS browser release roadmaps, but in case of Firefox, the current highest numbered verison, which is Firefox 60 (Nightly), does not support that feature. In may F60 will become the next ESR (Extended Support Release). If you care about ESR more than just "always the freshiest", probably you will have to wait about a year more, for next ESR. At this point probably is should be already implemented.


EDIT2:

2 years passed, time for update. In Firefox 78, released on June 30, 2020, lookbehind regex is finally implemented. What's more it is an ESR release. According to Can I Use, of the main browsers, only Safari still does not support this feature.

Upvotes: 3

gurvinder372
gurvinder372

Reputation: 68393

Split by /(?<!a)\//g

var output = "I Like this/ and a/ basketball is round a/a ups.Papa/ tol/d /me tha/t".split(/(?<!a)\//g);
console.log(output);

Explanation

  • /(?<!a)\/ matches / which is not preceded by a

Note

  • Works on chrome, doesn't work on FF as suggested by @SoulReaver in his comments.

Edit

Or alternatively, you can just split by /

var output = "I Like this/ and a/ basketball is round a/a ups.Papa/ tol/d /me tha/t".split(/\//g);
output = output.reduce( function(a,c){
  var lastItem = a.slice(-1)[0];
  //console.log(lastItem)
  if ( lastItem && lastItem.slice(-1) == "a" )
  {
     a.pop();
     a.push(lastItem.concat("/").concat(c));
  }
  else
  {
     a.push(c);
  }
  return a;
}, [])
console.log(output);

Edit 2

If a has to be ignored on either sides of /, then use the previous answer (based on reduce), just add the look-ahead in split

var output = "I Like this/ and a/ basketball is round a/a ups.Papa/ tol/d /me tha/t".split(/\/(?!=a)/g);

Upvotes: 5

Related Questions