0

I made this regular expression: /.net.(\w*)/

I'm trying to capture the qa in a string like this: https://xxxxxx.cloudfront.net/qa/club/Slide1.PNG

I'm doing .replace on it like so location.replace(/.net.(\w*)/,data.newName));

But instead of capturing qa, it captures .net, when I run the code in Javascript

According to this online regex tool made for ruby, it captures qa as intended

http://rubular.com/r/ItrG7BRNRn

What's the difference between Javascript regexes and Ruby regexes, and how can I make my regex work as intended in javascript?

Edit:

I changed my code to this:

var str = `https://xxxxxxxxxx.cloudfront.net/qa/club`;
var re = /\.net\/([^\/]*)\//;
console.log(data2.files[i].location.replace(re,'$1'+ "test"));

And instead of

https://dm7svtk8jb00c.cloudfront.net/test/club

I get this:

https://dm7svtk8jb00c.cloudfrontqatestclub

If I remove the $1 I get https://dm7svtk8jb00c.cloudfronttestclub, which is closer, but I want to keep the slashes.

3
  • Do you want the result to run in Ruby, or in JavaScript? location could be a variable in either language. Commented Jan 15, 2014 at 19:42
  • @theTinMan Javascript, sorry Commented Jan 15, 2014 at 20:21
  • 1
    BTW, if you want to test regex in JavaScript, I'd recommend regexpal.com or just use your Browser's console. Commented Jan 15, 2014 at 22:19

5 Answers 5

2

This would be a better regex:

/\.net\/([^\/]*)\//

Remember that . will match any character, not the period character. For that you need to escape it with a leading backslash: \.

Also, \w will only match numbers, letters and underscores. You could quite legitimately have a dash in that part of the URL. Therefore you're far better off matching anything that isn't a forward slash.

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

1 Comment

I changed my regex to the one that you provided, but it seems to remove the / characters from my string. I want to keep those
1

I am not sure how Ruby works, but JavaScript replace will not just replace the capture group, it replaces the whole matched string. By adding another capture group, you can use $1 to add back in the string you want to keep.

...replace(/(.net.)(\w*)/,"$1" + data.newName");

4 Comments

I changed my regex to the one that Jon suggested, and moving the capture group around makes some small changes, but I'm not getting the result that I want
Well Jon only has one capture group around the content you want to remove, so of course it does not work.
I made another capture group around (\.net\/) and it worked. I don't think I like capture groups very much.
I actually asked the wrong question. I actually wanted to capture one more level further, so club, not qa.
1

You have to do that like this:

location.replace(/(\.net.)(\w*)/, '$1' + data.newName)

replace replaces the whole matched substring, not a particular group. Ruby works exactly in the same way:

ruby -e "puts 'https://xxxxxx.cloudfront.net/qa/club/Slide1.PNG'.sub(/.net.(\w*)/, '@@')"
https://xxxxxx.cloudfront@@/club/Slide1.PNG

ruby -e "puts 'https://xxxxxx.cloudfront.net/qa/club/Slide1.PNG'.sub(/(.net.)(\w*)/, '\\1' + '@@')"
https://xxxxxx.cloudfront.net/@@/club/Slide1.PNG

Comments

1

There's no difference (at least with the pattern you've provided). In both cases, the expression matches ".net/qa", with qa being the first capture group within the expression. Notice that even in your linked example the entire match is highlighted.

I'd recommend something like this:

location.replace(/(.net.)\w*/, "$1" + data.newName);

Or this, to be a bit safer:

location.replace(/(.net.)\w*/, function(m, a) { return a + data.newName; });

Comments

1

It's not so much a different between JavaScript and Ruby's implementations of regular expressions, it's your pattern that needs a bit of work. It's not tight enough.

You can use something like /\.net\/([^\/]+)/, which you can see in action at Rubular. That returns the characters delimited by / following .net.

Regex patterns are very powerful, but they're also fraught with dangerous side-effects that open up big holes easily, causing false-positives, which can ruin results unexpectedly. Until you know them well, start simply, and test them every imaginable way. And, once you think you know them well, keep doing that; Patterns in code we write where I work are a particular hot-button for me, and I'm always finding holes in them in our code-reviews and requiring them to be tightened until they do exactly what the developer meant, not what they thought they meant.

While the pattern above works, I'd probably do it a bit differently in Ruby. Using the tools made for the job:

require 'uri'

URL = 'https://xxxxxx.cloudfront.net/qa/club/Slide1.PNG'
uri = URI.parse(URL)
path = uri.path # => "/qa/club/Slide1.PNG"
path.split('/')[1] # => "qa"

Or, more succinctly:

URI.parse(URL).path.split('/')[1] # => "qa"

Comments

Your Answer

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