2

I have this RegEx for C# ASP.NET MVC3 Model validation:

[RegularExpression(@"[0-9]*\,?[0-9]?[0-9]")]

This works for almost all cases, except if the number is bigger than 100. Any number greater than 100 should show error. I already tried use [Range], but it doesn't work with commas.

Valid: 0 / 0,0 / 0,00 - 100 / 100,0 / 100,00.

Invalid (Number > 100).

Community
  • 1
  • 1

2 Answers2

2

Not sure if zero's are only optional digits at the end but

 #  (?:100(?:,0{1,2})?|[0-9]{1,2}(?:,[0-9]{1,2})?)

 (?:
      100 
      (?: , 0{1,2} )?
   |  
      [0-9]{1,2} 
      (?: , [0-9]{1,2} )?
 )

Zero's only option at end

 #  (?:100|[0-9]{1,2})(?:,0{1,2})?

 (?:
      100 
   |  [0-9]{1,2} 
 )
 (?: , 0{1,2} )?

And, the permutations for no leading zero's except for zero itself

 # (?:100(?:,0{1,2})?|(?:0|[1-9][0-9]?)(?:,[0-9]{1,2})?) 

 (?:
      100 
      (?: , 0{1,2} )?
   |  
      (?:
           0
        |  
           [1-9] [0-9]? 
      )
      (?: , [0-9]{1,2} )?
 )


 # (?:100|0|[1-9][0-9])(?:,0{1,2})? 

 (?:
      100 
   |  
      0
   |  
      [1-9] [0-9] 
 )
 (?: , 0{1,2} )?
  • 1
    You need to include start and end of string controls, otherwise it will still match on larger numbers. Quick and dirty, "^(?:100|[0-9]{1,2})($|,0{1,2})$" works. – neilh Nov 27 '13 at 19:27
  • The OP didn't show ^$ anchors in the example. I won't either. And the quick & dirty regex obfuscates the anchors making it hard to read, while ^(?:100|[0-9]{1,2})(?:,0{1,2})?$ is ok because backtracking doesn't really have anywhere to go. –  Nov 27 '13 at 20:43
2

Here's a RegEx that matches your criteria:

^(?:(?:[0-9]|[1-9]{1,2})(?:,[0-9]{1,2})?|(?:100)(?:,0{1,2})?)$

(Given your use case, I have assumed that your character sequence appears by itself and is not embedded within other content. Please let me know if that is not the case.)

And here's a Perl program that demonstrates that RegEx on a sample data set. (Also see live demo.)

#!/usr/bin/env perl

use strict;
use warnings;

while (<DATA>) {
    chomp;

    # A1 => An integer between 1 and 99, without leading zeros.
    #      (Although zero can appear by itself.)
    #
    # A2 => A optional fractional component that may contain no more
    #       than two digits.
    #
    # -OR-
    #
    # B1 => The integer 100.
    #
    # B2 => A optional fractional component following that may
    #       consist of one or two zeros only.
    #

    if (/^(?:(?:[0-9]|[1-9]{1,2})(?:,[0-9]{1,2})?|(?:100)(?:,0{1,2})?)$/) {
    #           ^^^^^^^^A1^^^^^^    ^^^^^A2^^^^      ^B1    ^^^B2^^

        print "* [$_]\n";
    } else {
        print "  [$_]\n";
    }
}

__DATA__
0
01
11
99
100
101
0,0
0,00
01,00
0,000
99,00
99,99
100,0
100,00
100,000
100,01
100,99
101,00

Expected Output

* [0]
  [01]
* [11]
* [99]
* [100]
  [101]
* [0,0]
* [0,00]
  [01,00]
  [0,000]
* [99,00]
* [99,99]
* [100,0]
* [100,00]
  [100,000]
  [100,01]
  [100,99]
  [101,00]
DavidRR
  • 18,291
  • 25
  • 109
  • 191
  • 2
    One thing the OP states is `Valid: 0,00 - 100`. I can only assume > 100 would be `100.99` which your regex matches. Maybe you can provide for that with a slight modification - `^(?:[0-9]|[1-9][0-9]|100(?=(?:,0{1,2})?$))(?:,[0-9]{1,2})?$` , +1 Anyway –  Nov 28 '13 at 18:21
  • @sln - Right you are. And your regex works perfectly! However, I revised my regex somewhat differently so that the terminating `$` would appear only once. My approach: **A)** First check for one or two-digits and an optional fractional part, and then **B)** check for the number `100` and its optional fractional part (which may consist of one or two zeros only). I also included additional data samples. If you see any disadvantages with my revised regex vs. yours, please let me know. – DavidRR Nov 29 '13 at 16:22