0

I have the following URL:

localhost:3000/filter/shoes/color/white

I need to replace all slashes to - except the first slash from localhost:3000/.

The final URL must be:

localhost:3000/filter-shoes-color-white

I've tried some regex with ruby but I didn't have any success. Thanks.

3limin4t0r
  • 19,353
  • 2
  • 31
  • 52
jujajjjj
  • 55
  • 5

5 Answers5

1

Here is a regexp that match all the / but the first:

\G(?:\A[^\/]*\/)?+[^\/]*\K\/

So you can do:

"localhost:3000/filter/shoes/color/white".gsub(/\G(?:\A[^\/]*\/)?+[^\/]*\K\//,'-')
#=> "localhost:3000/filter-shoes-color-white"

But it won't work if you have a scheme on your URI.

Fravadona
  • 13,917
  • 1
  • 23
  • 35
0

TL;DR:

regex is:

\/(?<!localhost:3000\/)

Longer one

A famous old Chinese saying is: Teaching how to fishing is better than giving you the fish.

  1. For regex, you can use online regex site such as regex101.com to test immediately with your regex and test string. link
  2. Found other answers from stackoverflow using other key words to describe your situation: Regex for matching something if it is not preceded by something else
  3. Make you own magic.
R. Liu
  • 183
  • 8
  • It works but it's a little too specific to use `localhost:3000` as a negative look-behind – Fravadona Oct 21 '21 at 14:35
  • But it does answer the question, right? ;) Anyway, though I've provided the answer, my main point is more on the longer one, where developers can learn to concoct their own regex as there are already a lot of Q&A on regex on StackOverflow. – R. Liu Oct 21 '21 at 14:43
0

This is a pretty simple parsing problem, so I question the need for a regular expression. I think the code would probably be easier to understand and maintain if you just iterated through the characters of the string with a loop like this:

def transform(url)
  url = url.dup
  slash_count = 0
  (0...url.size).each do |i|
    if url[i] == '/'
      slash_count += 1
      url[i] = '-' if slash_count >= 2
    end
  end
  url
end

Here is something even simpler using Ruby's String#gsub method:

def transform2(url)
  slash_count = 0
  url.gsub('/') do
    slash_count += 1
    slash_count >= 2 ? '-' : '/'
  end
end
David Grayson
  • 84,103
  • 24
  • 152
  • 189
0

Using Ruby >= 2.7 with String#partition

Provided you aren't passing in a URI scheme like 'https://' as part of your string, you can do this as a single method chain with String#partition and String#tr. Using Ruby 3.0.2

'localhost:3000/filter-shoes-color-white'.partition(?/).
    map { _1.match?(/^\/$/) ? _1 : _1.tr(?/, ?-) }.join
#=> "localhost:3000/filter-shoes-color-white"

This basically relies on the fact that there are no forward slashes in the first array element returned by #partition, and the second element contains a slash and nothing else. You are then free to use #tr to replace forward slashes with dashes in the final element.

If you have an older Ruby, you'll need a different solution since String#partition wasn't introduced before Ruby 2.6.1. If you don't like using character literals, ternary operators, or numbered block arguments (introduced in Ruby 2.7), then you can refactor the solution to suit your own stylistic tastes.

Todd A. Jacobs
  • 81,402
  • 15
  • 141
  • 199
0

And another way of doing it. No regex and "localhost" lookback needed.

[url.split("/").take(2).join("/"),url.split("/").drop(2).join("-")].join("-")
Max
  • 361
  • 4
  • 16