tags:

views:

105

answers:

2

I need to match all valid URLs except:

http://www.w3.org
http://w3.org/foo
http://www.tempuri.org/foo

Generally, all URLs except certain domains.

Here is what I have so far:

https?://([-\w\.]+)+(:\d+)?(/([\w/_\.]*(\?\S+)?)?)?  

will match URLs that are close enough to my needs (but in no way all valid URLs!) (thanks, http://snipplr.com/view/2371/regex-regular-expression-to-match-a-url/!)

https?://www\.(?!tempuri|w3)\S*

will match all URLs with www., but not in the tempuri or w3 domain.

And I really want

https?://([-\w\.]+)(?!tempuri|w3)\S*

to work, but afaick, it seems to select all http:// strings.

Gah, I should just do this in something higher up the Chomsky hierarchy!

A: 

You're going down a slippery slope trying to validate URLs with regular expressions.

John at CashCommons
You incorrectly assume I'm attempting to validate URLs. Snide humor FTL.
Noel
"I need to match all *valid* URLs except" What part of this does not involve validation?
John at CashCommons
Semantics. The intent is not to prove a given URL valid. The intent is to match valid URLs. By implication, the regex could also match invalid URLs and not violate the sentence you quote, as long as it matches valid URLs except x. Jeff's post is for those who intend to validate a URL in order to use it as a URL. I gave no hint as to the intended use of the regex. That was your assumption.
Noel
Ahh ... light bulb ... "matching valid URLs" != "matching *only* valid URLs" right?
John at CashCommons
Yup. The wording was vague.
Noel
+1  A: 

The following regular expression:

https?://(?!w3|tempuri)([-\w]*\.)(?!w3|tempuri)\S*

only matches the first four lines from the following excerpt:

https://ok1.url.com
http://ok2.url.com
https://not.ok.tempuri.com
http://not-ok.either.w3.com

http://no1.w3.org
http://no2.w3.org
http://tempuri.bla.com
http://no4.tempuri.bla
http://no3.tempuri.org
http://w3.org/foo
http://www.tempuri.org/foo

I know what you're thinking, and the answer is that in order to match the above list and only return the first two lines you'd have to use the following regular expression:

https?://(?!w3|tempuri)([-\w]*\.)(?!w3|tempuri)([-\w]*\.)(?!w3|tempuri)\S*

which, in truth, is nothing more than a slight modification of the first regular expression, where the

(?!w3|tempuri)([-\w]*\.)

part appears twice in a row.

The reason why your regular expression wasn't working was because when you include . inside the ()* then that means it can not only match this. and this.this. but also this.this.th - in other words, it doesn't necessarily end in a dot, so it will force it to end wherever it has to so that the expression matches. Try it out in a regular expression tester and you'll see what I mean.

Pessimist
Yep, this works as advertised. However, now I realize that the Visual Studio search regex engine doesn't support lookaheads, so I'm off to simplify/sob quietly in a corner.
Noel
For the record, I ended up not being able to use either lookahead or the postfix ? operator. Silly. So I ran `[http|https]\://[^w3|^tempuri|^schemas][org|com|net]\S*` and then `[http|https]\://www\.[^w3|^tempuri|^schemas][org|com|net]\S*`. Boo.
Noel
That's very weird, because the regex I gave you I tested on the .Net regex engine... hmm I'll have to look into that. Maybe it's the .Net 3.5 thing? Do you have the latest?
Pessimist