Regular Expression to match both relative and absolute URLs

后端 未结 6 1228
自闭症患者
自闭症患者 2021-02-09 03:12

Anyone want to try their hand at coming up with a regex that matches both:

  • /foo/bar/baz.gif
  • /foo/bar/
  • http://www.foo.com/foo/bar

I

相关标签:
6条回答
  • 2021-02-09 03:39
    (
      ((http|https|ftp)://([\w-\d]+\.)+[\w-\d]+){0,1}  // Capture domain names or IP addresses
      (/[\w~,;\-\./?%&+#=]*)                // Capture paths, including relative
    )
    

    Rationale for this answer:

    1. The whole thing is grouped so you can pick out the entire URL
    2. The protocol portion is optional, but if provided, a hostname or IP address should also be provided (both of which have fewer allowed characters than the rest of the URI).
    3. The "/" at the beginning is also optional. Paths can be in the form "images/1.gif", which are relative to the current path rather than relative to the hostname.

    Caveats:

    1. mailto and file URIs not supported.
    2. URLs trailed by a period (such as at the end of a sentence without quotation) will include the trailing period.
    3. Because of #3 above, it's going to capture all sorts of things. If you can verify that all paths are not relative, you can add a "/" outside the parenthesis and thus require it.
    4. If all URIs are within HTML attributes (A, LINK, IMG, etc.), you can target the URIs much more accurately by only capturing within quotes, or at least only within HTML tags.

    Edit: whoops, fixed closing paren problem.

    0 讨论(0)
  • 2021-02-09 03:49

    I used naming capture groups. We get better matches when the scheme is present. Like www.foo.com/bar would only match /bar.

    (?:
      (?:(?<scheme>https?|file)://)
      (?<host>[^/]+)
      (?<path>/(?:[^\s])+)?
    )
    |
    (?<path>/(?:[^\s])+)
    

    This is what you could do for javascript

    var result = text.match(/(?:(?:(https?|file):\/\/)([^\/]+)(\/(?:[^\s])+)?)|(\/(?:[^\s])+)/g);
    

    Test data

    sadfasdf /foo/bar/ba090z.gif asdfasdf /foo/bar/ sadfasdf asdflkj; http://www.foo.com/foo/bar some stuff http://user:pw@www.foo.com:80/r?stuff%20stuff
    
    user:pw@www.foo.com:80/r?stuff%20stuff
    
    0 讨论(0)
  • 2021-02-09 03:51
    (http:/)?(/[\w.]+)+/?
    

    matches these, but maybe you had stricter conditions in mind?

    0 讨论(0)
  • 2021-02-09 03:53
    (http:\/)?(\/[\w\.\-]+)+\/?
    

    Similar to Alex's.

    0 讨论(0)
  • 2021-02-09 03:59

    That's a tricky one because there are so many valid characters in URL's (before they get url encoded).

    Here's my shot:

    (http:/|https:/)?(/[^\s"'<>]+)+/?
    

    Also similar to Alex's. The only problem I found with Alex's is that it wouldn't match things like pound signs, dashes, stuff like that. Whereas mine will match all of that.

    EDIT -- In fact the only thing that keeps it from being too greedy is the instruction to NOT match whitespace, quotes, apostrophes, or chevrons.

    0 讨论(0)
  • 2021-02-09 04:00

    Not easy and you maybe end up having "too much URI" catched, however what about:

    ((http://|https://)([^/])+)*(/([^\s])*(/))(((\w)*\.[\w]{3,10})|(\w+))?
    

    Basically you have a couple of groups there. On defining the protocol. One is looking for the directory and one is looking for a file at the end. But! this approach is very limited. If you need a real URI validation and! separation (port, username, password, filter out unwanted characters!) you will probably end up with a way more complex expression. Good luck!

    Update:

    You didn't asked for this, however for those guys coming from search engines wanting to learn more about regex I would like to plug this free program I used for this attempt "The Regex Coach" (Nope, not affiliated).

    0 讨论(0)
提交回复
热议问题