1

I'm trying to match slash that is followed by slash in url that is not part part of the protocol or query string.

Is there any other way to do this using REGEX but without lookbehind as it is not supported in all browsers?

My examples:

const urls = `
https://asdf.com//asdf//asdf
http://asdf.com//asdf//asdf
ftp://asdf.com//asdf//asdf
//asdf.com//asdf//asdf
//asdf.com//asdf//asdf?test=//
z39.50s://asdf//
`.replace(/(?<!(^[\w\d-.]{2,}\:|^|\?.*))\/(?=\/)/gim, '');
console.log(urls);
rjanjic
  • 2,640
  • 1
  • 15
  • 13

2 Answers2

3

You may use

.replace(/^(\S*?\/\/)|(\?.*)$|(\/)+/g, '$1$2$3')

See this regex demo

Details

  • ^(\S*?\/\/) - Group 1 (later referred to with $1 from the replacement pattern): 0 or more non-whitespace chars, as few as possible, from the start of the string, up to the first //
  • | - or
  • (\?.*)$ - Group 2 ($2): a ? char and the rest of the string
  • | - or
  • (\/)+ - Group 3 ($3) capturing a single / char, 1 or more times (each captured / will overwrite the previous one in the group memory buffer since it is a "repeated capturing group")
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
1

The normal workaround for the lookbehind deficit is to use a callback function
in the replace part.
The reason is that you have to match the errant part just to move the match position
past it. This requires logic in a callback function.

In %99.99 of the cases, you will have to do it this way if you have different replacements.

For the case you have it doesn't matter because you have a single replacement that is blank.
It gets masked by a combined group replacement where the stripping is controlled by
not having it in a group.

If you were to replace it with anything other than the empty string,
this is the only way to do it.

To that end, here is your (mostly) unaltered regex used with a callback.

     (                             # (1 start)
          (?: ^ [\w\d\-.]{2,} : | ^ | \? .* )
          //
     )                             # (1 end)
  |  /
     (?= / )

var urls = [
'https://asdf.com//asdf//asdf',
'http://asdf.com//asdf//asdf',
'ftp://asdf.com//asdf//asdf',
'//asdf.com//asdf//asdf',
'//asdf.com//asdf//asdf?test=//',
'z39.50s://asdf//' ];

for (var i = 0; i < urls.length; i++)
{
   urls[i] = urls[i].replace(
    /((?:^[\w\d\-.]{2,}:|^|\?.*)\/\/)|\/(?=\/)/gm,
    function(match, Grp1)
    {
      if ( Grp1 )
        return Grp1;
      return '';
    }
  );
}
console.log( urls );
animuson
  • 53,861
  • 28
  • 137
  • 147