views:

105

answers:

4

I'm trying to match any requests for a url that do not have a folder character (/) or end with an extension (.aspx). I can ignore querystring values and fragments in the regular expression for now. So far I have the following.

^([\w-/]+)(?!\.aspx|/)$

However, if I run this expression it selected the final / in the group which I don't want it to do. The goal is to append .aspx to urls that do not have it specified using Isapi ReWrite and then forward the request onto the .NET engine.

the example below shows all characters in a current match in bold

asd.aspx
this
something.aspx
this/test/ (dont want the final /)
this-test/ (dont want the final /)
this-test
this-test/that/test

Can anyone suggest an expression that would not select the final / if found in the expression?

+1  A: 

Move the / outside the group ():

^([\w-/]+)(?!\.aspx)/?$
Kimvais
Won't the /? never match, because the greedy + will always take it?
Douglas Leeder
The look-ahead assertion `(?!\.aspx)` as ther is nothing behind the end of the string.
Gumbo
It's a negative look-ahead assertion - I can't see how the final /? will ever match anything (i.e. it will always be the 0 of {0,1}).
Douglas Leeder
Ah, stupid me, should always test before posting.
Kimvais
A: 

Remove the / from the regex and add it outside and specify that it can have 0 or 1 occurrence.

^([\w-/]+)(?!.aspx)(/){0,1}$

Priyank Bolia
? is shorthand for {0,1} and there is no need to group the trailing /
Kimvais
you are right, but I didn't see the ? in your answer before, may be I miss that.
Priyank Bolia
+4  A: 

Try a look-behind assertion:

^([\w-/]+)(?<!/|\.aspx)$
Gumbo
Thank's Gumbo that worked perfect
WDuffy
I guess your regex engine allows variable-width look-behind assertions then?
Douglas Leeder
@Douglas Leeder: The look-behind has a fixed width: either one or five characters. Variable width would be to allow an infinite upper bound like `*` or `+` have.
Gumbo
+1  A: 

Your first sentence doesn't match your regular expression or examples.
It seems to me that you want:

  1. If the string ends with .aspx don't process further.
  2. Otherwise if the string ends with / remove that slash.
  3. Process the string.

Maybe you're trying to do too much with a regular expression?

Why not explicitly test for your extension (.aspx), and if you don't have that then detect a terminal slash and remove it, before extra processing of the string?

That is to say: I'm sure it's possible to create a regular expression, with negative lookahead, that will do 1 & 2, but wouldn't it be clearer to do it explicitly.

You might also want to test some more examples:

foo/bar/.aspx
foo/bar.aspx/
foo.aspx/bar
foo.aspx/bar/

Just to be sure you know what you're expecting as output.

Douglas Leeder
I checked the examples you supplied Douglas and thankfully they don't match using the regex which Gumbo supplied. Good thought though +1.
WDuffy
So is it your first sentance that is wrong?
Douglas Leeder