Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET Regex Error: [x-y] range in reverse order

Tags:

c#

regex

I am creating a Regex and so far I did this and tried it,

 ^([0][1-9]|1[0-2])[/-.] 

and I get the following error.

      parsing "^([0][1-9]|1[0-2])[/-.]" - [x-y] range in reverse order.        Description: An unhandled exception occurred during the execution of the current web request.                 Please review the stack trace for more information about the error and where it originated in         the code.         Exception Details: System.ArgumentException: parsing "^([0][1-9]|1[0-2])[/-.]" - [x-y] range        in reverse order. 

After messing around for a bit and trying to find error in my regex I simply changed me regex to

  ([0][1-9]|1[0-2])[-/.]  so basically only changed this [/-.] to [-/.] 

and it worked.

Then I tried some other combinations which worked.

   [/-]  [/.]  [/.-]  [/-?] 

Then I tried some others which didn't work.

   [/-\*]  [/-\+] 

So apparently "-" has problem at some places but no problem at others. Is that a bug? or am I missing something?

Update

Thanks guys for pointing out that "-" is assumed as range if it is in middle or not escaped by "\".

However, why did it work for [/-?] or [/-\?], is it really defining range here or taking it literally?

like image 218
Adnan Bhatti Avatar asked Sep 19 '11 20:09

Adnan Bhatti


2 Answers

Not a bug. Inside a character class (denoted by […]) the - character must be first (some flavours allow first or last, I believe) if it is to be included as a literal. Otherwise it is expected to denote a range, such as 0-9 or A-Z or even /-..

The problem is that according to Unicode, the . comes before the /, so the range is interpreted to be backward, equivalent to specifying a range 7-4.

If you used [.-/], I would not expect a parse exception, but you wouldn't get the results you expected.

like image 108
Jay Avatar answered Sep 30 '22 15:09

Jay


The problem is with this part:

[/-.] 

That means "the range of characters from '/' to '.'" - but '/' comes after '.' in Unicode, so the range makes no sense.

If you wanted it to mean "slash, dash or period" then you want:

[/\-.] 

... in other words, you need to escape the dash. Note that if this is in a regular C# string literal, you'll need to perform another level of escaping too:

string pattern = "[/\\-.]"; 

Using a verbatim string literal means you don't need to escape the backslash:

string pattern = @"[/\-.]"; 

Alternatively, as Jay suggested, you can just put the dash at the start:

[-/.] 

or end:

[/.-] 

(I've just tested, and all three of these options work.)

like image 41
Jon Skeet Avatar answered Sep 30 '22 15:09

Jon Skeet