28

If there is one thing I just cant get my head around, it's regex.

So after a lot of searching I finally found this one that suits my needs:

function get_domain_name()
    { 
    aaaa="http://www.somesite.se/blah/sdgsdgsdgs";
    //aaaa="http://somesite.se/blah/sese";
        domain_name_parts = aaaa.match(/:\/\/(.[^/]+)/)[1].split('.');
        if(domain_name_parts.length >= 3){
            domain_name_parts[0] = '';
        }
        var domain = domain_name_parts.join('.');
        if(domain.indexOf('.') == 0)
            alert("1"+ domain.substr(1));
        else
            alert("2"+ domain);
    }

It basically gives me back the domain name, is there anyway I can also get all the stuff after the domain name? in this case it would be /blah/sdgsdgsdgs from the aaaa variable.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
Ryan
  • 9,821
  • 22
  • 66
  • 101

6 Answers6

84

EDIT (2020): In modern browsers, you can use the built-in URL Web API.

https://developer.mozilla.org/en-US/docs/Web/API/URL/URL

var url = new URL("http://www.somesite.se/blah/sdgsdgsdgs");
var pathname = url.pathname; // returns /blah/sdgsdgsdgs

Instead of relying on a potentially unreliable* regex, you should instead use the built-in URL parser that the JavaScript DOM API provides:

var url = document.createElement('a');
url.href = "http://www.example.com/some/path?name=value#anchor";

That's all you need to do to parse the URL. Everything else is just accessing the parsed values:

url.protocol; //(http:)
url.hostname; //(www.example.com)
url.pathname; //(/some/path)
url.search; // (?name=value)
url.hash; //(#anchor)

In this case, if you're looking for /blah/sdgsdgsdgs, you'd access it with url.pathname

Basically, you're just creating a link (technically, anchor element) in JavaScript, and then you can make calls to the parsed pieces directly. (Since you're not adding it to the DOM, it doesn't add any invisible links anywhere.) It's accessed in the same way that values on the location object are.

(Inspired by this wonderful answer.)

EDIT: An important note: it appears that Internet Explorer has a bug where it omits the leading slash on the pathname attribute on objects like this. You could normalize it by doing something like:

 url.pathname = url.pathname.replace(/(^\/?)/,"/");

Note: *: I say "potentially unreliable", since it can be tempting to try to build or find an all-encompassing URL parser, but there are many, many conditions, edge cases and forgiving parsing techniques that might not be considered or properly supported; browsers are probably best at implementing (since parsing URLs is critical to their proper operation) this logic, so we should keep it simple and leave it to them.

Yahel
  • 37,023
  • 22
  • 103
  • 153
  • 1
    One worthwhile footnote: The only time I've found this to not be a good method is if you're parsing a large number of links; DOM element creation is more expensive than just regex. At a small number, the difference is indistinguishable. At 100+, it can have noticeable effects. – Yahel Feb 23 '12 at 13:13
  • 1
    Good call on normalizing the `pathname`! Are you sure there's no side effects from re-assigning the normalized `pathname`? Also, might I recommend removing the `()` from the regex? – Scott Rippey Sep 24 '12 at 17:33
  • 1
    giving this job to the browser is like: I hope the browser does it correctly... such as you mentioned, the IE bug might be an issue – nonopolarity Jul 02 '13 at 22:38
  • Is that code covered by the JavaScript DOM binding standard? - I didn't find it yet. – Nico Feb 26 '15 at 07:40
35

The RFC (see appendix B) provides a regular expression to parse the URI parts:

^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
 12            3  4          5       6  7        8 9

where

scheme    = $2
authority = $4
path      = $5
query     = $7
fragment  = $9

Example:

function parse_url(url) {
    var pattern = RegExp("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?");
    var matches =  url.match(pattern);
    return {
        scheme: matches[2],
        authority: matches[4],
        path: matches[5],
        query: matches[7],
        fragment: matches[9]
    };
}
console.log(parse_url("http://www.somesite.se/blah/sdgsdgsdgs"));

gives

Object
    authority: "www.somesite.se"
    fragment: undefined
    path: "/blah/sdgsdgsdgs"
    query: undefined
    scheme: "http"

DEMO

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • 6
    You can enhance the regular expression by using noncapturing groups. – Gumbo May 29 '11 at 14:40
  • 1
    I think I have to learn regex properly before I can understand your post mate, although I am sure it is extremely helpful. – Ryan May 29 '11 at 14:47
  • 4
    With non-capturing groups: `"^(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(\\?(?:[^#]*))?(#(?:.*))?"`. Returns only scheme, host, path, query and fragment. Note: `://` is not part of the scheme because the scheme can actually be omitted. – mark Feb 22 '13 at 17:53
  • 1
    This is dope af! Thanks for linking the RFC. Real heroes, those authors. – L0j1k Nov 09 '15 at 22:58
  • Additionally I would add, how to get the current URI: `document.URL` and how to parse the query: http://stackoverflow.com/a/2091331/1069083 – rubo77 Aug 09 '16 at 06:12
  • Be careful when copying mark's solution from his comment. An invisible UTF-8 character is copied due to the line break. I wasted an hour to figure out why the fragment-part doesn't work. Switching the encoding to ANSI in Notepad++ solved this mystery – fishbone Jan 25 '18 at 07:17
3

Please note that this solution is not the best. I made this just to match the requirements of the OP. I personally would suggest looking into the other answers.

THe following regexp will give you back the domain and the rest. :\/\/(.[^\/]+)(.*):

  1. www.google.com
  2. /goosomething

I suggest you studying the RegExp documentation here: http://www.regular-expressions.info/reference.html

Using your function:

function get_domain_name()
    { 
    aaaa="http://www.somesite.se/blah/sdgsdgsdgs";
    //aaaa="http://somesite.se/blah/sese";
        var matches = aaaa.match(/:\/\/(?:www\.)?(.[^/]+)(.*)/);
        alert(matches[1]);
        alert(matches[2]);
    }
MarioRicalde
  • 9,131
  • 6
  • 40
  • 42
  • can alert(matches[1]); return it without the "www."? alert(matches[2]); is perfect! And thanks for the link. – Ryan May 29 '11 at 14:45
  • Just what I asked for, special thank you! (Thank you everyone else who replied as well!) – Ryan May 29 '11 at 15:06
  • 1
    @kuroir can't you re-set the "accepted" solution to the one with most votes? I'm pretty sure you can do that... – Robin Winslow Oct 25 '12 at 14:41
3

You just need to modify your regex a bit. For example:

var aaaa="http://www.somesite.se/blah/sdgsdgsdgs";
var m = aaaa.match(/^[^:]*:\/\/([^\/]+)(\/.*)$/);

m will then contain the following parts:

["http://www.somesite.se/blah/sdgsdgsdgs", "www.somesite.se", "/blah/sdgsdgsdgs"]

Here is the same example, but modified so that it will split out the "www." part. I think the regular expression should be written so that the match will work whether or not you you have the "www." part. So check this out:

var aaaa="http://www.somesite.se/blah/sdgsdgsdgs";
var m = aaaa.match(/^[^:]*:\/\/(www\.)?([^\/]+)(\/.*)$/);

m will then contain the following parts:

["http://www.somesite.se/blah/sdgsdgsdgs", "www.", "somesite.se", "/blah/sdgsdgsdgs"]

Now check out the same regular expression but with a url that does not start with "www.":

var bbbb="http://somesite.se/blah/sdgsdgsdgs";
var m = .match(/^[^:]*:\/\/(www\.)?([^\/]+)(\/.*)$/);

Now your match looks like this:

["http://somesite.se/blah/sdgsdgsdgs", undefined, "somesite.se", "/blah/sdgsdgsdgs"]

So as you can see it will do the right thing in both cases.

gordyt
  • 101
  • 3
  • Hey! Thanks for replying! No, I need the second part to be without the "www." exactly like in the original. And the second part like you wrote above. Thanks! – Ryan May 29 '11 at 14:42
  • EDIT; I meant: No, I need the second part to be without the "www." exactly like in the original. And the third part like you wrote above is perfect. Thanks! – Ryan May 29 '11 at 14:49
2

There is a nice jQuery plugin for parsing URLs: Purl.

All the regex stuff is hidden inside, and you get something like:

> url = $.url("http://markdown.com/awesome/language/markdown.html?show=all#top");

> url.attr('source');
"http://markdown.com/awesome/language/markdown.html?show=all#top"

> url.attr('protocol');
"http"

> url.attr('host');
"markdown.com"

> url.attr('relative');
"/awesome/language/markdown.html?show=all#top"

> url.attr('path');
"/awesome/language/markdown.html"

> url.attr('directory');
"/awesome/language/"

> url.attr('file');
"markdown.html"

> url.attr('query');
"show=all"

> url.attr('fragment');
"top"
SherylHohman
  • 16,580
  • 17
  • 88
  • 94
weekens
  • 8,064
  • 6
  • 45
  • 62
2

Browsers have come a long way since this question was first asked. You can now use the native URL interface to accomplish this:

const url = new URL('http://www.somesite.se/blah/sdgsdgsdgs')

console.log(url.host) // "www.somesite.se"
console.log(url.href) // "http://www.somesite.se/blah/sdgsdgsdgs"
console.log(url.origin) // "http://www.somesite.se"
console.log(url.pathname) // "/blah/sdgsdgsdgs"
console.log(url.protocol) // "http:"
// etc.

Be aware that IE does not support this API. But, you can easily polyfill it with polyfill.io:

<script crossorigin="anonymous" src="https://polyfill.io/v3/polyfill.min.js?flags=gated&features=URL"></script>
zgreen
  • 4,182
  • 1
  • 24
  • 19