Regular Expression to match both relative and abso

2020-06-03 08:39发布

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

I think it might be impossible to do it with one regex, but you never know.

EDIT: To clarify, what I'm trying to do is pick out all URI's from a document (Not a HTML document).

标签: regex
6条回答
放我归山
2楼-- · 2020-06-03 08:59
(http:\/)?(\/[\w\.\-]+)+\/?

Similar to Alex's.

查看更多
对你真心纯属浪费
3楼-- · 2020-06-03 09:00
(
  ((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.

查看更多
够拽才男人
4楼-- · 2020-06-03 09:06
(http:/)?(/[\w.]+)+/?

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

查看更多
The star\"
5楼-- · 2020-06-03 09:11

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.

查看更多
啃猪蹄的小仙女
6楼-- · 2020-06-03 09:18

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
查看更多
Bombasti
7楼-- · 2020-06-03 09:19

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).

查看更多
登录 后发表回答