开发者

Find a url for a file in html using a regular expression

I've set myself a somewhat ambitious first task in learning regular expressions (and one which relates to a problem I'm trying to solve). I need to find any instance of a url that ends in .m4v, in a big html string.

My first attempt was this for jpg files

http.*jpg

Which of course seems correct on first glance, but of course returns stuf开发者_StackOverflowf like this:

http://domain.com/page.html" title="Misc"><img src="http://domain.com/image.jpg

Which does match the expression in theory. So really, I need to put something in http.*m4v that says 'only the closest instance between http and m4v'. Any ideas?


As you've noticed, an expression such as the following is greedy:

http:.*\.jpg

That means it reads as much input as possible while satisfying the expression.

It's the "*" operator that makes it greedy. There's a well-defined regex technique to making this non-greedy… use the "?" modifier after the "*".

http:.*?\.jpg

Now it will match as little as possible while still satisifying the expression (i.e. it will stop searching at the first occurrence of ".jpg".

Of course, if you have a .jpg in the middle of a URL, like:

http://mydomain.com/some.jpg-folder/foo.jpg

It will not match the full URL.

You'll want to define the end of the URL as something that can't be considered part of the URL, such as a space, or a new line, or (if the URL in nested inside parentheses), a closing parenthesis. This can't be solved with just one little regex however if it's included in written language, since URLs are often ambiguous.

Take for example:

At this page, http://mysite.com/puppy.html, there's a cute little puppy dog.

The comma could technically be a part of a URL. You have to deal with a lot of ambiguities like this when looking for URLs in written text, and it's hard not to have bugs due to the ambiguities.

EDIT | Here's an example of a regex in PHP that is a quick and dirty solution, being greedy only where needed and trying to deal with the English language:

<?php

$str = "Checkout http://www.foo.com/test?items=bat,ball, for info about bats and balls";

preg_match('/https?:\/\/([a-zA-Z0-9][a-zA-Z0-9-]*)(\.[a-zA-Z0-9-]+)*((\/[^\s]*)(?=[\s\.,;!\?]))\b/i', $str, $matches);

var_dump($matches);

It outputs:

array(5) {
  [0]=>
  string(38) "http://www.foo.com/test?items=bat,ball"
  [1]=>
  string(3) "www"
  [2]=>
  string(4) ".com"
  [3]=>
  string(20) "/test?items=bat,ball"
  [4]=>
  string(20) "/test?items=bat,ball"
}

The explanation is in the comments.


Perl, ruby, php and javascript should all work with these:

/(http:\/\/(?:(?:(?!\http:\/\/).))+\.jpg)/

The URLs will be stored in the matched groups. Tested this out against "http://a.com/b.jpg-folder/c.jpg http://mydomain.com/some.jpg-folder/foo.jpg" and it worked correctly without being too greedy.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜